"""WebSocket proxy: authenticated users ↔ Tracker.""" import asyncio import logging import json from fastapi import APIRouter, WebSocket, WebSocketDisconnect import websockets from auth import verify_token from config import TRACKER_WS_URL, TRACKER_TOKEN logger = logging.getLogger("bff.ws") router = APIRouter() @router.websocket("/ws") async def ws_proxy(ws: WebSocket, token: str = ""): # Authenticate user if not token: await ws.close(code=4001, reason="No token") return user = verify_token(token) if not user: await ws.close(code=4001, reason="Invalid token") return await ws.accept() logger.info("WS connected: %s", user.get("name")) # Connect to tracker tracker_url = f"{TRACKER_WS_URL}?client_type=human&client_id={user['sub']}&token={TRACKER_TOKEN}" try: async with websockets.connect(tracker_url) as tracker_ws: async def forward_to_tracker(): try: while True: data = await ws.receive_text() await tracker_ws.send(data) except WebSocketDisconnect: pass async def forward_to_client(): try: async for msg in tracker_ws: await ws.send_text(msg) except Exception: pass await asyncio.gather(forward_to_tracker(), forward_to_client()) except Exception as e: logger.error("WS proxy error: %s", e) finally: logger.info("WS disconnected: %s", user.get("name"))