""" SLMM API Proxy Forwards /api/slmm/* requests to the SLMM backend service """ import httpx import logging from fastapi import APIRouter, Request, Response, WebSocket from fastapi.responses import StreamingResponse from app.core.config import SLMM_API_URL logger = logging.getLogger(__name__) router = APIRouter(prefix="/api/slmm", tags=["slmm-proxy"]) @router.api_route("/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "PATCH"]) async def proxy_slmm_request(path: str, request: Request): """Proxy HTTP requests to SLMM backend""" # Build target URL - rewrite /api/slmm/* to /api/nl43/* target_url = f"{SLMM_API_URL}/api/nl43/{path}" # Get query params query_string = str(request.url.query) if query_string: target_url += f"?{query_string}" logger.info(f"Proxying {request.method} {target_url}") # Read request body body = await request.body() # Forward headers (exclude host) headers = { key: value for key, value in request.headers.items() if key.lower() not in ['host', 'content-length'] } async with httpx.AsyncClient(timeout=30.0) as client: try: # Make proxied request response = await client.request( method=request.method, url=target_url, content=body, headers=headers ) # Return response return Response( content=response.content, status_code=response.status_code, headers=dict(response.headers) ) except httpx.RequestError as e: logger.error(f"Proxy request failed: {e}") return Response( content=f'{{"detail": "SLMM backend unavailable: {str(e)}"}}', status_code=502, media_type="application/json" ) @router.websocket("/{unit_id}/live") async def proxy_slmm_websocket(websocket: WebSocket, unit_id: str): """Proxy WebSocket connections to SLMM backend for live data streaming""" await websocket.accept() # Build WebSocket URL ws_protocol = "ws" if "localhost" in SLMM_API_URL or "127.0.0.1" in SLMM_API_URL else "wss" ws_url = SLMM_API_URL.replace("http://", f"{ws_protocol}://").replace("https://", f"{ws_protocol}://") ws_target = f"{ws_url}/api/slmm/{unit_id}/live" logger.info(f"Proxying WebSocket to {ws_target}") async with httpx.AsyncClient() as client: try: async with client.stream("GET", ws_target) as response: async for chunk in response.aiter_bytes(): await websocket.send_bytes(chunk) except Exception as e: logger.error(f"WebSocket proxy error: {e}") await websocket.close(code=1011, reason=f"Backend error: {str(e)}")