fix(config): carry the public port into derived endpoints (#2329)

This commit is contained in:
Hampus authored and GitHub committed 2026-09-01 20:47:18 +02:00
1 parent a93f9dd0af
commit bc40073a02
21 files changed
+2037 -55

No files matched your search

@@ -4,6 +4,15 @@ import {Config} from '../Config';
import {Logger} from '../Logger';
import {VoiceRepository} from './VoiceRepository';
export function resolveLivekitEndpoint(configuredUrl: string | undefined, apiPublicUrl: string): string {
if (configuredUrl) {
return configuredUrl;
}
const apiPublic = new URL(apiPublicUrl);
const protocol = apiPublic.protocol === 'https:' ? 'wss' : 'ws';
return `${protocol}://${apiPublic.host}/livekit`;
}
export class VoiceDataInitializer {
async initialize(): Promise<void> {
if (!Config.voice.enabled || !Config.voice.defaultRegion) {
@@ -19,7 +28,7 @@ export class VoiceDataInitializer {
try {
const repository = new VoiceRepository();
const serverId = `${defaultRegion.id}-server-1`;
const livekitEndpoint = this.resolveLivekitEndpoint();
const livekitEndpoint = resolveLivekitEndpoint(Config.voice.url, Config.endpoints.apiPublic);
const existingRegions = await repository.listRegions();
if (existingRegions.length === 0) {
Logger.info('[VoiceDataInitializer] Creating default voice region from config...');
@@ -91,12 +100,4 @@ export class VoiceDataInitializer {
Logger.error({error}, '[VoiceDataInitializer] Failed to initialise config-managed voice topology');
}
}
private resolveLivekitEndpoint(): string {
if (Config.voice.url) {
return Config.voice.url;
}
const protocol = new URL(Config.endpoints.apiPublic).protocol.slice(0, -1) === 'https' ? 'wss' : 'ws';
return `${protocol}://${new URL(Config.endpoints.apiPublic).hostname}/livekit`;
}
}
@@ -0,0 +1,48 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {describe, expect, it} from 'vitest';
import {resolveLivekitEndpoint} from '../VoiceDataInitializer';
describe('resolveLivekitEndpoint', () => {
it('keeps the public port when the instance does not serve on the default port', () => {
expect(resolveLivekitEndpoint(undefined, 'http://inplace.localhost:19480/api')).toBe(
'ws://inplace.localhost:19480/livekit',
);
expect(resolveLivekitEndpoint('', 'https://fluxer.example.com:8443/api')).toBe(
'wss://fluxer.example.com:8443/livekit',
);
});
it('omits the port when the public endpoint uses the default port for its scheme', () => {
expect(resolveLivekitEndpoint(undefined, 'https://fluxer.example.com/api')).toBe(
'wss://fluxer.example.com/livekit',
);
expect(resolveLivekitEndpoint(undefined, 'https://fluxer.example.com:443/api')).toBe(
'wss://fluxer.example.com/livekit',
);
expect(resolveLivekitEndpoint(undefined, 'http://fluxer.example.com:80/api')).toBe(
'ws://fluxer.example.com/livekit',
);
});
it('maps https to wss and http to ws', () => {
expect(resolveLivekitEndpoint(undefined, 'https://fluxer.example.com/api')).toBe(
'wss://fluxer.example.com/livekit',
);
expect(resolveLivekitEndpoint(undefined, 'http://fluxer.example.com/api')).toBe('ws://fluxer.example.com/livekit');
});
it('brackets ipv6 literals so the derived endpoint stays parseable', () => {
expect(resolveLivekitEndpoint(undefined, 'http://[::1]:19480/api')).toBe('ws://[::1]:19480/livekit');
expect(resolveLivekitEndpoint(undefined, 'https://[2001:db8::1]/api')).toBe('wss://[2001:db8::1]/livekit');
const derived = new URL(resolveLivekitEndpoint(undefined, 'http://[::1]:19480/api'));
expect(derived.host).toBe('[::1]:19480');
expect(derived.pathname).toBe('/livekit');
});
it('returns the configured voice url unchanged when one is set', () => {
expect(resolveLivekitEndpoint('wss://voice.example.com', 'http://inplace.localhost:19480/api')).toBe(
'wss://voice.example.com',
);
});
});