2025-07-22 17:01:12 +02:00
|
|
|
# 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.
|
|
|
|
|
"""
|
2025-07-23 07:26:04 +02:00
|
|
|
# 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
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
2025-07-22 17:01:12 +02:00
|
|
|
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")
|