Skip to content

Commit 95222d0

Browse files
committed
🐛(frontend) add LiveKit connection warmup for Firefox+proxy fixes
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.
1 parent d44b45b commit 95222d0

File tree

3 files changed

+40
-2
lines changed

3 files changed

+40
-2
lines changed

src/backend/core/api/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ def get_frontend_configuration(request):
5050
else None,
5151
"default_country": settings.ROOM_TELEPHONY_DEFAULT_COUNTRY,
5252
},
53+
"livekit": {"url": settings.LIVEKIT_CONFIGURATION["url"]},
5354
}
5455
frontend_configuration.update(settings.FRONTEND_CONFIGURATION)
5556
return Response(frontend_configuration)

src/frontend/src/api/useConfig.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ export interface ApiConfig {
3737
default_country?: string
3838
}
3939
manifest_link?: string
40+
livekit: {
41+
url: string
42+
}
4043
}
4144

4245
const fetchConfig = (): Promise<ApiConfig> => {

src/frontend/src/features/rooms/components/Conference.tsx

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { LocalUserChoices } from '@/stores/userChoices'
2424
import { navigateTo } from '@/navigation/navigateTo'
2525
import { MediaDeviceErrorAlert } from './MediaDeviceErrorAlert'
2626
import { usePostHog } from 'posthog-js/react'
27+
import { useConfig } from '@/api/useConfig'
2728

2829
export const Conference = ({
2930
roomId,
@@ -37,12 +38,15 @@ export const Conference = ({
3738
initialRoomData?: ApiRoom
3839
}) => {
3940
const posthog = usePostHog()
41+
const { data: apiConfig } = useConfig()
4042

4143
useEffect(() => {
4244
posthog.capture('visit-room', { slug: roomId })
4345
}, [roomId, posthog])
4446
const fetchKey = [keys.room, roomId]
4547

48+
const [isConnectionWarmedUp, setIsConnectionWarmedUp] = useState(false)
49+
4650
const {
4751
mutateAsync: createRoom,
4852
status: createStatus,
@@ -53,6 +57,36 @@ export const Conference = ({
5357
},
5458
})
5559

60+
/**
61+
* Warm up connection to LiveKit server before joining room
62+
* This prefetch helps reduce initial connection latency by establishing
63+
* an early HTTP connection to the WebRTC signaling server
64+
*
65+
* FIREFOX + PROXY WORKAROUND:
66+
* On Firefox behind proxy configurations, WebSocket signaling fails to establish.
67+
* Client receives HTTP 200 instead of expected 101 (Switching Protocols).
68+
* This appears to be a certificate/security issue where the initial request
69+
* is considered unsecure. By first calling the signaling server via HTTPS,
70+
* subsequent WebSocket establishment works correctly in these setups.
71+
* This is a temporary workaround - issue is reproducible on LiveKit's demo app.
72+
*/
73+
useEffect(() => {
74+
const warmUpLivekitConnection = async () => {
75+
if (isConnectionWarmedUp || !apiConfig) return
76+
try {
77+
// Make a lightweight HTTPS request to establish secure connection
78+
// This resolves Firefox+proxy WebSocket handshake issues
79+
await fetch(apiConfig.livekit.url, { method: 'HEAD' })
80+
setIsConnectionWarmedUp(true)
81+
} catch (error) {
82+
// Don't block room connection if warmup fails
83+
console.warn('LiveKit connection warmup failed:', error)
84+
setIsConnectionWarmedUp(true)
85+
}
86+
}
87+
warmUpLivekitConnection()
88+
}, [isConnectionWarmedUp, apiConfig])
89+
5690
const {
5791
status: fetchStatus,
5892
isError: isFetchError,
@@ -125,9 +159,9 @@ export const Conference = ({
125159
<Screen header={false} footer={false}>
126160
<LiveKitRoom
127161
room={room}
128-
serverUrl={data?.livekit?.url}
162+
serverUrl={apiConfig?.livekit.url}
129163
token={data?.livekit?.token}
130-
connect={true}
164+
connect={isConnectionWarmedUp}
131165
audio={userConfig.audioEnabled}
132166
video={
133167
userConfig.videoEnabled && {

0 commit comments

Comments
 (0)