import asyncio import logging import httpx import websockets from fastapi import APIRouter, Request, WebSocket, WebSocketDisconnect, Response from config import get_config logger = logging.getLogger(__name__) router = APIRouter(prefix="/api/go2rtc") @router.post("/webrtc") async def proxy_webrtc(request: Request, src: str): """Proxy WebRTC SDP exchange to go2rtc.""" config = get_config() target = f"{config.go2rtc.url}/api/webrtc?src={src}" body = await request.body() async with httpx.AsyncClient() as client: resp = await client.post( target, content=body, headers={"Content-Type": "application/sdp"}, timeout=10.0, ) return Response( content=resp.content, status_code=resp.status_code, media_type="application/sdp", ) @router.websocket("/ws") async def proxy_mse_ws(ws: WebSocket, src: str): """Proxy MSE WebSocket to go2rtc.""" config = get_config() go2rtc_ws_url = config.go2rtc.url.replace("http", "ws") target = f"{go2rtc_ws_url}/api/ws?src={src}" await ws.accept() try: async with websockets.connect( target, ping_interval=None, ping_timeout=None, close_timeout=5, ) as upstream: async def forward_to_client(): async for msg in upstream: if isinstance(msg, bytes): await ws.send_bytes(msg) else: await ws.send_text(msg) async def forward_to_upstream(): while True: data = await ws.receive_text() await upstream.send(data) await asyncio.gather( forward_to_client(), forward_to_upstream(), ) except (WebSocketDisconnect, websockets.ConnectionClosed, Exception): pass