Go Live: MediaMTX credentials via X-Stream-Auth -> Authorization on the Caddy->MediaMTX hop (WebRTC ignores query params); fix WHIP session DELETE path
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -56,11 +56,14 @@ export async function publish({ stream, path, user, pass, onState }) {
|
||||
const offer = await pc.createOffer()
|
||||
await pc.setLocalDescription(offer)
|
||||
await new Promise(res => { if (pc.iceGatheringState === 'complete') return res(); const t = setTimeout(res, 2000); pc.onicegatheringstatechange = () => { if (pc.iceGatheringState === 'complete') { clearTimeout(t); res() } } })
|
||||
const url = `/webrtc/${path}/whip?user=${encodeURIComponent(user)}&pass=${encodeURIComponent(pass)}`
|
||||
const r = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/sdp' }, body: pc.localDescription.sdp, credentials: 'same-origin' })
|
||||
// MediaMTX takes WebRTC credentials only in an Authorization header ("Bearer user:pass"). We send them as
|
||||
// X-Stream-Auth and Caddy rewrites the header on the MediaMTX hop, so Authentik's gate never sees it.
|
||||
const auth = { 'X-Stream-Auth': `Bearer ${user}:${pass}` }
|
||||
const r = await fetch(`/webrtc/${path}/whip`, { method: 'POST', headers: { 'Content-Type': 'application/sdp', ...auth }, body: pc.localDescription.sdp, credentials: 'same-origin' })
|
||||
if (!r.ok) { pc.close(); throw new Error(r.status === 401 || r.status === 403 ? 'stream key rejected' : r.status === 400 && /busy|already/i.test(await r.text().catch(() => '')) ? 'that stream name is already live (OBS running?)' : `publish failed (${r.status})`) }
|
||||
await pc.setRemoteDescription({ type: 'answer', sdp: await r.text() })
|
||||
const session = r.headers.get('Location')
|
||||
let session = r.headers.get('Location') // MediaMTX answers relative to its own root
|
||||
if (session && session.startsWith('/') && !session.startsWith('/webrtc/')) session = '/webrtc' + session
|
||||
return {
|
||||
pc,
|
||||
stats: async () => {
|
||||
@@ -71,7 +74,7 @@ export async function publish({ stream, path, user, pass, onState }) {
|
||||
return { kbps, fps, w, h }
|
||||
},
|
||||
stop: async () => {
|
||||
try { if (session) await fetch(session.startsWith('http') ? new URL(session).pathname : session, { method: 'DELETE', credentials: 'same-origin' }) } catch {}
|
||||
try { if (session) await fetch(session.startsWith('http') ? '/webrtc' + new URL(session).pathname : session, { method: 'DELETE', headers: auth, credentials: 'same-origin' }) } catch {}
|
||||
pc.close()
|
||||
stream.getTracks().forEach(t => t.stop())
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user