From 387bc2e1f4084c726ae3f9dce8026ae7dd053d95 Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Wed, 23 Jul 2025 11:50:02 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B(frontend)=20add=20LiveKit=20connec?= =?UTF-8?q?tion=20warmup=20for=20Firefox+proxy=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement HTTPS prefetch before joining rooms to resolve WebSocket handshake failures where Firefox+proxy returns HTTP 200 instead of 101. Reproduced locally with Squid container. No proxy configuration fixes found - HTTPS warmup is only working workaround. Issue doesn't occur when signaling server shares webapp domain, making warmup unnecessary. Use HEAD request to minimize bandwidth. --- src/backend/core/api/__init__.py | 1 + src/frontend/src/api/useConfig.ts | 3 ++ .../features/rooms/components/Conference.tsx | 38 ++++++++++++++++++- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/backend/core/api/__init__.py b/src/backend/core/api/__init__.py index 8a419ee5..05ac309d 100644 --- a/src/backend/core/api/__init__.py +++ b/src/backend/core/api/__init__.py @@ -50,6 +50,7 @@ def get_frontend_configuration(request): else None, "default_country": settings.ROOM_TELEPHONY_DEFAULT_COUNTRY, }, + "livekit": {"url": settings.LIVEKIT_CONFIGURATION["url"]}, } frontend_configuration.update(settings.FRONTEND_CONFIGURATION) return Response(frontend_configuration) diff --git a/src/frontend/src/api/useConfig.ts b/src/frontend/src/api/useConfig.ts index b1673a50..876775da 100644 --- a/src/frontend/src/api/useConfig.ts +++ b/src/frontend/src/api/useConfig.ts @@ -37,6 +37,9 @@ export interface ApiConfig { default_country?: string } manifest_link?: string + livekit: { + url: string + } } const fetchConfig = (): Promise => { diff --git a/src/frontend/src/features/rooms/components/Conference.tsx b/src/frontend/src/features/rooms/components/Conference.tsx index a2dc831f..d84cc6cd 100644 --- a/src/frontend/src/features/rooms/components/Conference.tsx +++ b/src/frontend/src/features/rooms/components/Conference.tsx @@ -24,6 +24,7 @@ import { LocalUserChoices } from '@/stores/userChoices' import { navigateTo } from '@/navigation/navigateTo' import { MediaDeviceErrorAlert } from './MediaDeviceErrorAlert' import { usePostHog } from 'posthog-js/react' +import { useConfig } from '@/api/useConfig' export const Conference = ({ roomId, @@ -37,12 +38,15 @@ export const Conference = ({ initialRoomData?: ApiRoom }) => { const posthog = usePostHog() + const { data: apiConfig } = useConfig() useEffect(() => { posthog.capture('visit-room', { slug: roomId }) }, [roomId, posthog]) const fetchKey = [keys.room, roomId] + const [isConnectionWarmedUp, setIsConnectionWarmedUp] = useState(false) + const { mutateAsync: createRoom, status: createStatus, @@ -53,6 +57,36 @@ export const Conference = ({ }, }) + /** + * Warm up connection to LiveKit server before joining room + * This prefetch helps reduce initial connection latency by establishing + * an early HTTP connection to the WebRTC signaling server + * + * FIREFOX + PROXY WORKAROUND: + * On Firefox behind proxy configurations, WebSocket signaling fails to establish. + * Client receives HTTP 200 instead of expected 101 (Switching Protocols). + * This appears to be a certificate/security issue where the initial request + * is considered unsecure. By first calling the signaling server via HTTPS, + * subsequent WebSocket establishment works correctly in these setups. + * This is a temporary workaround - issue is reproducible on LiveKit's demo app. + */ + useEffect(() => { + const warmUpLivekitConnection = async () => { + if (isConnectionWarmedUp || !apiConfig) return + try { + // Make HTTPS request to establish secure connection + // This resolves Firefox+proxy WebSocket handshake issues + await fetch(apiConfig.livekit.url) + setIsConnectionWarmedUp(true) + } catch (error) { + // Don't block room connection if warmup fails + console.warn('LiveKit connection warmup failed:', error) + setIsConnectionWarmedUp(true) + } + } + warmUpLivekitConnection() + }, [isConnectionWarmedUp, apiConfig]) + const { status: fetchStatus, isError: isFetchError, @@ -125,9 +159,9 @@ export const Conference = ({