From b0c7dcbc9a4ae1434503b31d1a429d318a9c5217 Mon Sep 17 00:00:00 2001 From: cruizba Date: Mon, 2 Feb 2026 19:14:20 +0100 Subject: [PATCH] Introduce base path configuration and update related services --- meet-ce/backend/src/environment.ts | 1 + meet-ce/backend/src/server.ts | 64 ++++++---- .../backend/src/utils/html-injection.utils.ts | 111 ++++++++++++++++++ meet-ce/backend/src/utils/url.utils.ts | 35 ++++-- .../pages/meeting/meeting.component.ts | 6 +- .../services/meeting-context.service.ts | 7 +- .../lib/shared/services/app-config.service.ts | 59 ++++++++++ .../src/lib/shared/services/index.ts | 1 + .../src/lib/shared/services/sound.service.ts | 11 +- meet-ce/frontend/webcomponent/tests/README.md | 2 +- meet-ce/frontend/webcomponent/tests/config.ts | 2 +- testapp/.env | 4 +- testapp/src/controllers/homeController.ts | 2 +- testapp/src/services/configService.ts | 4 +- 14 files changed, 262 insertions(+), 47 deletions(-) create mode 100644 meet-ce/backend/src/utils/html-injection.utils.ts create mode 100644 meet-ce/frontend/projects/shared-meet-components/src/lib/shared/services/app-config.service.ts diff --git a/meet-ce/backend/src/environment.ts b/meet-ce/backend/src/environment.ts index 8a2e2d2d..846c9bd5 100644 --- a/meet-ce/backend/src/environment.ts +++ b/meet-ce/backend/src/environment.ts @@ -23,6 +23,7 @@ export const MEET_ENV = { LOG_LEVEL: process.env.MEET_LOG_LEVEL || 'info', NAME_ID: process.env.MEET_NAME_ID || 'openviduMeet', BASE_URL: process.env.MEET_BASE_URL ?? '', + BASE_PATH: process.env.MEET_BASE_PATH || '/meet', EDITION: process.env.MEET_EDITION || 'CE', // Authentication configuration diff --git a/meet-ce/backend/src/server.ts b/meet-ce/backend/src/server.ts index c1226a4e..831807a1 100644 --- a/meet-ce/backend/src/server.ts +++ b/meet-ce/backend/src/server.ts @@ -1,7 +1,7 @@ import chalk from 'chalk'; import cookieParser from 'cookie-parser'; import cors from 'cors'; -import express, { Express, Request, Response } from 'express'; +import express, { Express, Request, Response, Router } from 'express'; import { initializeEagerServices, registerDependencies } from './config/dependency-injector.config.js'; import { INTERNAL_CONFIG } from './config/internal-config.js'; import { MEET_ENV, logEnvVars } from './environment.js'; @@ -17,6 +17,7 @@ import { internalMeetingRouter } from './routes/meeting.routes.js'; import { recordingRouter } from './routes/recording.routes.js'; import { internalRoomRouter, roomRouter } from './routes/room.routes.js'; import { userRouter } from './routes/user.routes.js'; +import { getBasePath, getInjectedHtml } from './utils/html-injection.utils.js'; import { frontendDirectoryPath, frontendHtmlPath, @@ -27,6 +28,7 @@ import { const createApp = () => { const app: Express = express(); + const basePath = getBasePath(); // Enable CORS support if (MEET_ENV.SERVER_CORS_ORIGIN) { @@ -38,9 +40,6 @@ const createApp = () => { ); } - // Serve static files - app.use(express.static(frontendDirectoryPath)); - // Configure trust proxy based on deployment topology // This is important for rate limiting and getting the real client IP // Can be: true, false, a number (hops), or a custom function/string @@ -69,55 +68,74 @@ const createApp = () => { app.use(setBaseUrlFromRequest); } + // Create a router for all app routes (to be mounted under base path) + const appRouter: Router = express.Router(); + + // Serve static files (disable automatic index.html serving so our catch-all can inject config) + appRouter.use(express.static(frontendDirectoryPath, { index: false })); + // Public API routes - app.use(`${INTERNAL_CONFIG.API_BASE_PATH_V1}/docs`, (_req: Request, res: Response) => + appRouter.use(`${INTERNAL_CONFIG.API_BASE_PATH_V1}/docs`, (_req: Request, res: Response) => res.sendFile(publicApiHtmlFilePath) ); - app.use(`${INTERNAL_CONFIG.API_BASE_PATH_V1}/rooms`, /*mediaTypeValidatorMiddleware,*/ roomRouter); - app.use(`${INTERNAL_CONFIG.API_BASE_PATH_V1}/recordings`, /*mediaTypeValidatorMiddleware,*/ recordingRouter); + appRouter.use(`${INTERNAL_CONFIG.API_BASE_PATH_V1}/rooms`, /*mediaTypeValidatorMiddleware,*/ roomRouter); + appRouter.use(`${INTERNAL_CONFIG.API_BASE_PATH_V1}/recordings`, /*mediaTypeValidatorMiddleware,*/ recordingRouter); // Internal API routes if (process.env.NODE_ENV === 'development') { // Serve internal API docs only in development mode - app.use(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/docs`, (_req: Request, res: Response) => + appRouter.use(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/docs`, (_req: Request, res: Response) => res.sendFile(internalApiHtmlFilePath) ); } - app.use(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/auth`, authRouter); - app.use(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/api-keys`, apiKeyRouter); - app.use(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/users`, userRouter); - app.use(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/rooms`, internalRoomRouter); - app.use(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/meetings`, internalMeetingRouter); - // app.use(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/recordings`, internalRecordingRouter); - app.use(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/config`, configRouter); - app.use(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/analytics`, analyticsRouter); + appRouter.use(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/auth`, authRouter); + appRouter.use(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/api-keys`, apiKeyRouter); + appRouter.use(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/users`, userRouter); + appRouter.use(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/rooms`, internalRoomRouter); + appRouter.use(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/meetings`, internalMeetingRouter); + // appRouter.use(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/recordings`, internalRecordingRouter); + appRouter.use(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/config`, configRouter); + appRouter.use(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/analytics`, analyticsRouter); - app.use('/health', (_req: Request, res: Response) => res.status(200).send('OK')); + appRouter.use('/health', (_req: Request, res: Response) => res.status(200).send('OK')); // LiveKit Webhook route - app.use('/livekit/webhook', livekitWebhookRouter); + appRouter.use('/livekit/webhook', livekitWebhookRouter); // Serve OpenVidu Meet webcomponent bundle file - app.get('/v1/openvidu-meet.js', (_req: Request, res: Response) => res.sendFile(webcomponentBundlePath)); - // Serve OpenVidu Meet index.html file for all non-API routes - app.get(/^(?!.*\/(api|internal-api)\/).*$/, (_req: Request, res: Response) => res.sendFile(frontendHtmlPath)); + appRouter.get('/v1/openvidu-meet.js', (_req: Request, res: Response) => res.sendFile(webcomponentBundlePath)); + // Serve OpenVidu Meet index.html file for all non-API routes (with dynamic base path injection) + appRouter.get(/^(?!.*\/(api|internal-api)\/).*$/, (_req: Request, res: Response) => { + res.type('html').send(getInjectedHtml(frontendHtmlPath)); + }); // Catch all other routes and return 404 - app.use((_req: Request, res: Response) => + appRouter.use((_req: Request, res: Response) => res.status(404).json({ error: 'Path Not Found', message: 'API path not implemented' }) ); + // Mount all routes under the configured base path + app.use(basePath, appRouter); + return app; }; const startServer = (app: express.Application) => { + const basePath = getBasePath(); + const basePathDisplay = basePath === '/' ? '' : basePath.slice(0, -1); + app.listen(MEET_ENV.SERVER_PORT, async () => { console.log(' '); console.log('---------------------------------------------------------'); console.log(' '); console.log(`OpenVidu Meet ${MEET_ENV.EDITION} is listening on port`, chalk.cyanBright(MEET_ENV.SERVER_PORT)); + + if (basePath !== '/') { + console.log('Base Path:', chalk.cyanBright(basePath)); + } + console.log( 'REST API Docs: ', - chalk.cyanBright(`http://localhost:${MEET_ENV.SERVER_PORT}${INTERNAL_CONFIG.API_BASE_PATH_V1}/docs`) + chalk.cyanBright(`http://localhost:${MEET_ENV.SERVER_PORT}${basePathDisplay}${INTERNAL_CONFIG.API_BASE_PATH_V1}/docs`) ); logEnvVars(); }); diff --git a/meet-ce/backend/src/utils/html-injection.utils.ts b/meet-ce/backend/src/utils/html-injection.utils.ts new file mode 100644 index 00000000..200c1489 --- /dev/null +++ b/meet-ce/backend/src/utils/html-injection.utils.ts @@ -0,0 +1,111 @@ +import chalk from 'chalk'; +import fs from 'fs'; +import { MEET_ENV } from '../environment.js'; + +let cachedHtml: string | null = null; +let configValidated = false; + +/** + * Normalizes the base path to ensure it starts and ends with / + * @param basePath The base path to normalize + * @returns Normalized base path (e.g., '/', '/meet/', '/app/path/') + */ +export function normalizeBasePath(basePath: string): string { + let normalized = basePath.trim(); + + // Handle empty string + if (!normalized) { + return '/'; + } + + // Ensure it starts with / + if (!normalized.startsWith('/')) { + normalized = '/' + normalized; + } + + // Ensure it ends with / + if (!normalized.endsWith('/')) { + normalized = normalized + '/'; + } + + return normalized; +} + +/** + * Validates the BASE_URL and BASE_PATH configuration and warns about potential issues. + * Only runs once per process. + */ +function validateBasePathConfig(): void { + if (configValidated) return; + + configValidated = true; + + const baseUrl = MEET_ENV.BASE_URL; + const basePath = MEET_ENV.BASE_PATH; + + if (baseUrl) { + try { + const url = new URL(baseUrl); + + // Check if BASE_URL contains a path (other than just /) + if (url.pathname && url.pathname !== '/') { + console.warn(chalk.yellow('⚠️ WARNING: MEET_BASE_URL contains a path segment:'), chalk.cyan(url.pathname)); + console.warn(chalk.yellow(' MEET_BASE_URL should only contain https protocol and host (e.g., https://example.com)')); + console.warn(chalk.yellow(' Use MEET_BASE_PATH for the deployment path (e.g., /meet/)')); + + if (basePath && basePath !== '/') { + console.warn(chalk.red(` This may cause issues: BASE_URL path "${url.pathname}" + BASE_PATH "${basePath}"`)); + } + } + } catch { + console.warn(chalk.yellow('⚠️ WARNING: MEET_BASE_URL is not a valid URL:'), chalk.cyan(baseUrl)); + } + } +} + +/** + * Gets the configured base path, normalized + * @returns The normalized base path from MEET_BASE_PATH environment variable + */ +export function getBasePath(): string { + validateBasePathConfig(); + return normalizeBasePath(MEET_ENV.BASE_PATH); +} + +/** + * Injects runtime configuration into the index.html + * - Replaces the tag with the configured base path + * - Injects a script with window.__OPENVIDU_MEET_CONFIG__ for frontend access + * + * @param htmlPath Path to the index.html file + * @returns The modified HTML content + */ +export function getInjectedHtml(htmlPath: string): string { + // In production, cache the result for performance + if (process.env.NODE_ENV === 'production' && cachedHtml) { + return cachedHtml; + } + + const basePath = getBasePath(); + let html = fs.readFileSync(htmlPath, 'utf-8'); + + // Replace the base href - handle both possible formats + html = html.replace(//i, ``); + + // Inject runtime configuration script before the closing tag + const configScript = ``; + html = html.replace('', `${configScript}\n`); + + if (process.env.NODE_ENV === 'production') { + cachedHtml = html; + } + + return html; +} + +/** + * Clears the cached HTML (useful for testing or config changes) + */ +export function clearHtmlCache(): void { + cachedHtml = null; +} diff --git a/meet-ce/backend/src/utils/url.utils.ts b/meet-ce/backend/src/utils/url.utils.ts index 8a053618..1d0ac9cb 100644 --- a/meet-ce/backend/src/utils/url.utils.ts +++ b/meet-ce/backend/src/utils/url.utils.ts @@ -1,33 +1,46 @@ import { container } from '../config/dependency-injector.config.js'; import { MEET_ENV } from '../environment.js'; import { BaseUrlService } from '../services/base-url.service.js'; +import { getBasePath } from './html-injection.utils.js'; /** - * Returns the base URL for the application. + * Returns the base URL for the application, including the configured base path. * * If the global `BASE_URL` variable is defined, it returns its value, * ensuring there is no trailing slash and removing default ports (443 for HTTPS, 80 for HTTP). * Otherwise, it retrieves the base URL from the `HttpContextService` instance. * - * @returns {string} The base URL as a string. + * The configured BASE_PATH is appended to the URL (without trailing slash). + * + * @returns {string} The base URL as a string (e.g., 'https://example.com/meet'). */ export const getBaseUrl = (): string => { + let hostUrl: string; + if (MEET_ENV.BASE_URL) { - let baseUrl = MEET_ENV.BASE_URL.endsWith('/') ? MEET_ENV.BASE_URL.slice(0, -1) : MEET_ENV.BASE_URL; + hostUrl = MEET_ENV.BASE_URL.endsWith('/') ? MEET_ENV.BASE_URL.slice(0, -1) : MEET_ENV.BASE_URL; // Remove default port 443 for HTTPS URLs - if (baseUrl.startsWith('https://') && baseUrl.includes(':443')) { - baseUrl = baseUrl.replace(':443', ''); + if (hostUrl.startsWith('https://') && hostUrl.includes(':443')) { + hostUrl = hostUrl.replace(':443', ''); } // Remove default port 80 for HTTP URLs - if (baseUrl.startsWith('http://') && baseUrl.includes(':80')) { - baseUrl = baseUrl.replace(':80', ''); + if (hostUrl.startsWith('http://') && hostUrl.includes(':80')) { + hostUrl = hostUrl.replace(':80', ''); } - - return baseUrl; + } else { + const baseUrlService = container.get(BaseUrlService); + hostUrl = baseUrlService.getBaseUrl(); } - const baseUrlService = container.get(BaseUrlService); - return baseUrlService.getBaseUrl(); + // Append the base path (without trailing slash) + const basePath = getBasePath(); + + if (basePath === '/') { + return hostUrl; + } + + // Remove trailing slash from base path for the final URL + return `${hostUrl}${basePath.slice(0, -1)}`; }; diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/pages/meeting/meeting.component.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/pages/meeting/meeting.component.ts index a3462edf..5265fae8 100644 --- a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/pages/meeting/meeting.component.ts +++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/pages/meeting/meeting.component.ts @@ -12,6 +12,7 @@ import { } from 'openvidu-components-angular'; import { Subject } from 'rxjs'; import { ApplicationFeatures } from '../../../../shared/models/app.model'; +import { AppConfigService } from '../../../../shared/services/app-config.service'; import { FeatureConfigurationService } from '../../../../shared/services/feature-configuration.service'; import { GlobalConfigService } from '../../../../shared/services/global-config.service'; import { NotificationService } from '../../../../shared/services/notification.service'; @@ -72,6 +73,7 @@ export class MeetingComponent implements OnInit { protected eventHandlerService = inject(MeetingEventHandlerService); protected captionsService = inject(MeetingCaptionsService); protected soundService = inject(SoundService); + protected appConfigService = inject(AppConfigService); protected destroy$ = new Subject(); // === LOBBY PHASE COMPUTED SIGNALS (when showLobby = true) === @@ -208,7 +210,9 @@ export class MeetingComponent implements OnInit { // } async onViewRecordingsClicked() { - window.open(`/room/${this.roomId()}/recordings?secret=${this.roomSecret()}`, '_blank'); + const basePath = this.appConfigService.basePath; + const basePathForUrl = basePath.endsWith('/') ? basePath.slice(0, -1) : basePath; + window.open(`${basePathForUrl}/room/${this.roomId()}/recordings?secret=${this.roomSecret()}`, '_blank'); } onParticipantConnected(event: any): void { diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-context.service.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-context.service.ts index 7f8a38c1..7d1cd922 100644 --- a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-context.service.ts +++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-context.service.ts @@ -1,6 +1,7 @@ import { computed, effect, inject, Injectable, signal } from '@angular/core'; import { MeetRoom } from 'node_modules/@openvidu-meet/typings/dist/room'; import { ParticipantService, Room, ViewportService } from 'openvidu-components-angular'; +import { AppConfigService } from '../../../shared/services/app-config.service'; import { FeatureConfigurationService } from '../../../shared/services/feature-configuration.service'; import { SessionStorageService } from '../../../shared/services/session-storage.service'; import { CustomParticipantModel } from '../models'; @@ -18,6 +19,7 @@ export class MeetingContextService { private readonly featureConfigService = inject(FeatureConfigurationService); private readonly viewportService = inject(ViewportService); private readonly sessionStorageService = inject(SessionStorageService); + private readonly appConfigService = inject(AppConfigService); private readonly _meetRoom = signal(undefined); private readonly _lkRoom = signal(undefined); @@ -166,7 +168,10 @@ export class MeetingContextService { */ private setMeetingUrl(roomId: string): void { const hostname = window.location.origin.replace('http://', '').replace('https://', ''); - const meetingUrl = roomId ? `${hostname}/room/${roomId}` : ''; + const basePath = this.appConfigService.basePath; + // Remove trailing slash from base path for URL construction + const basePathForUrl = basePath.endsWith('/') ? basePath.slice(0, -1) : basePath; + const meetingUrl = roomId ? `${hostname}${basePathForUrl}/room/${roomId}` : ''; this._meetingUrl.set(meetingUrl); } diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/services/app-config.service.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/services/app-config.service.ts new file mode 100644 index 00000000..3c552746 --- /dev/null +++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/services/app-config.service.ts @@ -0,0 +1,59 @@ +import { Injectable } from '@angular/core'; + +declare global { + interface Window { + __OPENVIDU_MEET_CONFIG__?: { + basePath: string; + }; + } +} + +/** + * Service that provides access to runtime application configuration. + * Reads configuration injected by the server at runtime. + */ +@Injectable({ + providedIn: 'root' +}) +export class AppConfigService { + private _basePath: string; + + constructor() { + // Read from injected config, fallback to document base element, then to '/' + this._basePath = window.__OPENVIDU_MEET_CONFIG__?.basePath || this.getBasePathFromDocument() || '/'; + } + + /** + * Gets the configured base path (e.g., '/', '/meet/', '/app/path/') + */ + get basePath(): string { + return this._basePath; + } + + /** + * Resolves an asset path relative to the base path. + * Use this for assets that need absolute paths (e.g., Audio elements). + * + * @param assetPath The asset path starting with 'assets/' (no leading slash) + * @returns The full path including the base path (e.g., '/meet/assets/sounds/file.mp3') + */ + resolveAssetPath(assetPath: string): string { + // Remove leading slash if present + const cleanPath = assetPath.startsWith('/') ? assetPath.slice(1) : assetPath; + + // Combine with base path + return `${this._basePath}${cleanPath}`; + } + + private getBasePathFromDocument(): string | null { + try { + const baseElement = document.querySelector('base'); + if (baseElement) { + return baseElement.getAttribute('href') || null; + } + } catch (e) { + console.warn('Could not read base element:', e); + } + return null; + } +} diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/services/index.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/services/index.ts index a94ffef1..982c1175 100644 --- a/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/services/index.ts +++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/services/index.ts @@ -1,5 +1,6 @@ export * from './analytics.service'; export * from './api-key.service'; +export * from './app-config.service'; export * from './app-data.service'; export * from './feature-configuration.service'; export * from './global-config.service'; diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/services/sound.service.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/services/sound.service.ts index b926b163..21987cd2 100644 --- a/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/services/sound.service.ts +++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/services/sound.service.ts @@ -1,17 +1,20 @@ -import { Injectable } from '@angular/core'; +import { inject, Injectable } from '@angular/core'; +import { AppConfigService } from './app-config.service'; /** * Service responsible for managing sound effects within the application. */ @Injectable() export class SoundService { + private appConfig = inject(AppConfigService); + constructor() {} /** * Plays a sound to indicate that a participant has joined the meeting. */ playParticipantJoinedSound(): void { - const audio = new Audio('/assets/sounds/participant-joined.mp3'); + const audio = new Audio(this.appConfig.resolveAssetPath('assets/sounds/participant-joined.mp3')); audio.volume = 0.4; audio.play(); } @@ -20,7 +23,7 @@ export class SoundService { * Plays a sound to indicate that a participant's role has been upgraded. */ playParticipantRoleUpgradedSound(): void { - const audio = new Audio('/assets/sounds/role-upgraded.wav'); + const audio = new Audio(this.appConfig.resolveAssetPath('assets/sounds/role-upgraded.wav')); audio.volume = 0.4; audio.play(); } @@ -30,7 +33,7 @@ export class SoundService { * Plays a sound to indicate that a participant's role has been downgraded. */ playParticipantRoleDowngradedSound(): void { - const audio = new Audio('/assets/sounds/role-downgraded.wav'); + const audio = new Audio(this.appConfig.resolveAssetPath('assets/sounds/role-downgraded.wav')); audio.volume = 0.4; audio.play(); } diff --git a/meet-ce/frontend/webcomponent/tests/README.md b/meet-ce/frontend/webcomponent/tests/README.md index 91d0cdfa..43fa88da 100644 --- a/meet-ce/frontend/webcomponent/tests/README.md +++ b/meet-ce/frontend/webcomponent/tests/README.md @@ -343,7 +343,7 @@ pnpm test:e2e-recording-access # Recording access control tests Tests require the following configuration (defined in `tests/config.ts`): ```typescript -MEET_API_URL # Backend API URL (default: http://localhost:6080) +MEET_API_URL # Backend API URL (default: http://localhost:6080/meet) MEET_API_KEY # API key for backend (default: meet-api-key) MEET_TESTAPP_URL # Test application URL (default: http://localhost:5080) RUN_MODE # Execution mode: 'CI' or 'development' diff --git a/meet-ce/frontend/webcomponent/tests/config.ts b/meet-ce/frontend/webcomponent/tests/config.ts index ef08c64a..9ceab143 100644 --- a/meet-ce/frontend/webcomponent/tests/config.ts +++ b/meet-ce/frontend/webcomponent/tests/config.ts @@ -1,4 +1,4 @@ export const RUN_MODE = process.env['RUN_MODE'] || 'development'; -export const MEET_API_URL = process.env['MEET_API_URL'] || 'http://localhost:6080'; +export const MEET_API_URL = process.env['MEET_API_URL'] || 'http://localhost:6080/meet'; export const MEET_API_KEY = process.env['MEET_API_KEY'] || 'meet-api-key'; export const MEET_TESTAPP_URL = process.env['MEET_TESTAPP_URL'] || 'http://localhost:5080'; diff --git a/testapp/.env b/testapp/.env index c7504915..7625b106 100644 --- a/testapp/.env +++ b/testapp/.env @@ -1,4 +1,4 @@ SERVER_PORT=5080 -MEET_API_URL=http://localhost:6080/api/v1 +MEET_API_URL=http://localhost:6080/meet/api/v1 MEET_API_KEY=meet-api-key -MEET_WEBCOMPONENT_SRC=http://localhost:6080/v1/openvidu-meet.js +MEET_WEBCOMPONENT_SRC=http://localhost:6080/meet/v1/openvidu-meet.js diff --git a/testapp/src/controllers/homeController.ts b/testapp/src/controllers/homeController.ts index 247fbd5e..66f179e0 100644 --- a/testapp/src/controllers/homeController.ts +++ b/testapp/src/controllers/homeController.ts @@ -23,7 +23,7 @@ export const getHome = async (_req: Request, res: Response) => { console.error('Error details:', { message: error instanceof Error ? error.message : 'Unknown error', stack: error instanceof Error ? error.stack : 'No stack trace', - apiUrl: process.env.MEET_API_URL || 'http://localhost:6080/api/v1', + apiUrl: process.env.MEET_API_URL || 'http://localhost:6080/meet/api/v1', apiKey: process.env.MEET_API_KEY || 'meet-api-key' }); res.status(500).send( diff --git a/testapp/src/services/configService.ts b/testapp/src/services/configService.ts index 0356024f..e07c76d4 100644 --- a/testapp/src/services/configService.ts +++ b/testapp/src/services/configService.ts @@ -10,9 +10,9 @@ export class ConfigService { constructor() { this.serverPort = process.env.SERVER_PORT ? parseInt(process.env.SERVER_PORT, 10) : 5080; - this.meetApiUrl = process.env.MEET_API_URL || 'http://localhost:6080/api/v1'; + this.meetApiUrl = process.env.MEET_API_URL || 'http://localhost:6080/meet/api/v1'; this.meetApiKey = process.env.MEET_API_KEY || 'meet-api-key'; - this.meetWebhookSrc = process.env.MEET_WEBCOMPONENT_SRC || 'http://localhost:6080/v1/openvidu-meet.js'; + this.meetWebhookSrc = process.env.MEET_WEBCOMPONENT_SRC || 'http://localhost:6080/meet/v1/openvidu-meet.js'; } }