# gateway/app/routes/nominatim.py from fastapi import APIRouter, Request, HTTPException from fastapi.responses import JSONResponse import httpx import structlog from app.core.config import settings logger = structlog.get_logger() router = APIRouter() @router.get("/search") async def proxy_nominatim_search(request: Request): """ Proxies requests to the Nominatim geocoding search API. """ # Handle OPTIONS requests directly for CORS if request.method == "OPTIONS": return Response( status_code=200, headers={ "Access-Control-Allow-Origin": settings.CORS_ORIGINS_LIST, "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS", "Access-Control-Allow-Headers": "Content-Type, Authorization, X-Tenant-ID", "Access-Control-Allow-Credentials": "true", "Access-Control-Max-Age": "86400" # Cache preflight for 24 hours } ) try: # Construct the internal Nominatim URL # All query parameters from the client request are forwarded nominatim_url = f"{settings.NOMINATIM_SERVICE_URL}/nominatim/search" # httpx client for making async HTTP requests async with httpx.AsyncClient(timeout=30.0) as client: response = await client.get( nominatim_url, params=request.query_params # Forward all query parameters from frontend ) response.raise_for_status() # Raise an exception for HTTP errors (4xx or 5xx) # Return the JSON response from Nominatim directly return JSONResponse(content=response.json()) except httpx.RequestError as exc: logger.error("Nominatim service request failed", error=str(exc)) raise HTTPException( status_code=503, detail=f"Nominatim service unavailable: {exc}" ) except httpx.HTTPStatusError as exc: logger.error(f"Nominatim service responded with error {exc.response.status_code}", detail=exc.response.text) raise HTTPException( status_code=exc.response.status_code, detail=f"Nominatim service error: {exc.response.text}" ) except Exception as exc: logger.error("Unexpected error in Nominatim proxy", error=str(exc)) raise HTTPException(status_code=500, detail="Internal server error in Nominatim proxy")