from __future__ import annotations import os import httpx from fastapi import APIRouter, HTTPException, Request from fastapi.responses import JSONResponse TOOLS_API_URL = os.getenv("TOOLS_API_URL", "http://tools-api:8700").rstrip("/") router = APIRouter(prefix="/api/ops", tags=["ops-api"]) async def _proxy(method: str, path: str, request: Request) -> JSONResponse: body = await request.body() upstream = f"{TOOLS_API_URL}/ops{path}" try: async with httpx.AsyncClient(timeout=30.0) as client: resp = await client.request( method=method, url=upstream, params=dict(request.query_params), content=body if body else None, headers={"content-type": request.headers.get("content-type", "application/json")}, ) except Exception as exc: # noqa: BLE001 raise HTTPException(status_code=502, detail=f"tools-api unavailable: {exc}") from exc if resp.status_code >= 500: raise HTTPException(status_code=502, detail=f"tools-api error {resp.status_code}") try: payload = resp.json() except Exception: # noqa: BLE001 payload = {"raw": resp.text} return JSONResponse(status_code=resp.status_code, content=payload) @router.get("/status") async def ops_status_proxy(request: Request): return await _proxy("GET", "/status", request) @router.get("/topology") async def ops_topology_proxy(request: Request): return await _proxy("GET", "/topology", request) @router.post("/refresh") async def ops_refresh_proxy(request: Request): return await _proxy("POST", "/refresh", request) @router.api_route("/{subpath:path}", methods=["GET", "POST", "PUT", "PATCH", "DELETE"]) async def ops_generic_proxy(subpath: str, request: Request): return await _proxy(request.method, f"/{subpath}", request)