Add POI feature and imporve the overall backend implementation
This commit is contained in:
@@ -22,7 +22,7 @@ from app.middleware.rate_limit import RateLimitMiddleware
|
||||
from app.middleware.subscription import SubscriptionMiddleware
|
||||
from app.middleware.demo_middleware import DemoMiddleware
|
||||
from app.middleware.read_only_mode import ReadOnlyModeMiddleware
|
||||
from app.routes import auth, tenant, notification, nominatim, subscription, demo, pos
|
||||
from app.routes import auth, tenant, notification, nominatim, subscription, demo, pos, geocoding, poi_context
|
||||
from shared.monitoring.logging import setup_logging
|
||||
from shared.monitoring.metrics import MetricsCollector
|
||||
|
||||
@@ -71,6 +71,8 @@ app.include_router(tenant.router, prefix="/api/v1/tenants", tags=["tenants"])
|
||||
app.include_router(subscription.router, prefix="/api/v1", tags=["subscriptions"])
|
||||
app.include_router(notification.router, prefix="/api/v1/notifications", tags=["notifications"])
|
||||
app.include_router(nominatim.router, prefix="/api/v1/nominatim", tags=["location"])
|
||||
app.include_router(geocoding.router, prefix="/api/v1/geocoding", tags=["geocoding"])
|
||||
app.include_router(poi_context.router, prefix="/api/v1/poi-context", tags=["poi-context"])
|
||||
app.include_router(pos.router, prefix="/api/v1/pos", tags=["pos"])
|
||||
app.include_router(demo.router, prefix="/api/v1", tags=["demo"])
|
||||
|
||||
|
||||
74
gateway/app/routes/geocoding.py
Normal file
74
gateway/app/routes/geocoding.py
Normal file
@@ -0,0 +1,74 @@
|
||||
# gateway/app/routes/geocoding.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.api_route("/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"])
|
||||
async def proxy_geocoding(request: Request, path: str):
|
||||
"""
|
||||
Proxies all geocoding requests to the External Service geocoding endpoints.
|
||||
|
||||
Forwards requests from /api/v1/geocoding/* to external-service:8000/api/v1/geocoding/*
|
||||
"""
|
||||
try:
|
||||
# Construct the external service URL
|
||||
external_url = f"{settings.EXTERNAL_SERVICE_URL}/api/v1/geocoding/{path}"
|
||||
|
||||
# Get request body for POST/PUT/PATCH
|
||||
body = None
|
||||
if request.method in ["POST", "PUT", "PATCH"]:
|
||||
body = await request.body()
|
||||
|
||||
# Forward headers (excluding host)
|
||||
headers = {
|
||||
key: value
|
||||
for key, value in request.headers.items()
|
||||
if key.lower() not in ["host", "content-length"]
|
||||
}
|
||||
|
||||
# Make the proxied request
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.request(
|
||||
method=request.method,
|
||||
url=external_url,
|
||||
params=request.query_params,
|
||||
headers=headers,
|
||||
content=body
|
||||
)
|
||||
|
||||
# Return the response from external service
|
||||
return JSONResponse(
|
||||
content=response.json() if response.text else None,
|
||||
status_code=response.status_code,
|
||||
headers=dict(response.headers)
|
||||
)
|
||||
|
||||
except httpx.RequestError as exc:
|
||||
logger.error("External service geocoding request failed", error=str(exc), path=path)
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
detail=f"Geocoding service unavailable: {exc}"
|
||||
)
|
||||
except httpx.HTTPStatusError as exc:
|
||||
logger.error(
|
||||
f"External service geocoding responded with error {exc.response.status_code}",
|
||||
detail=exc.response.text,
|
||||
path=path
|
||||
)
|
||||
raise HTTPException(
|
||||
status_code=exc.response.status_code,
|
||||
detail=f"Geocoding service error: {exc.response.text}"
|
||||
)
|
||||
except Exception as exc:
|
||||
logger.error("Unexpected error in geocoding proxy", error=str(exc), path=path)
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail="Internal server error in geocoding proxy"
|
||||
)
|
||||
91
gateway/app/routes/poi_context.py
Normal file
91
gateway/app/routes/poi_context.py
Normal file
@@ -0,0 +1,91 @@
|
||||
"""
|
||||
POI Context Proxy Router
|
||||
Forwards all POI context requests to the External Service
|
||||
"""
|
||||
|
||||
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.api_route("/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"])
|
||||
async def proxy_poi_context(request: Request, path: str):
|
||||
"""
|
||||
Proxies all POI context requests to the External Service.
|
||||
|
||||
Forwards requests from /api/v1/poi-context/* to external-service:8000/api/v1/poi-context/*
|
||||
|
||||
Args:
|
||||
request: The incoming request
|
||||
path: The path after /api/v1/poi-context/
|
||||
|
||||
Returns:
|
||||
JSONResponse with the response from the external service
|
||||
|
||||
Raises:
|
||||
HTTPException: If the external service is unavailable or returns an error
|
||||
"""
|
||||
try:
|
||||
# Construct the external service URL
|
||||
external_url = f"{settings.EXTERNAL_SERVICE_URL}/poi-context/{path}"
|
||||
|
||||
logger.debug("Proxying POI context request",
|
||||
method=request.method,
|
||||
path=path,
|
||||
external_url=external_url)
|
||||
|
||||
# Get request body for POST/PUT/PATCH requests
|
||||
body = None
|
||||
if request.method in ["POST", "PUT", "PATCH"]:
|
||||
body = await request.body()
|
||||
|
||||
# Copy headers (exclude host and content-length as they'll be set by httpx)
|
||||
headers = {
|
||||
key: value
|
||||
for key, value in request.headers.items()
|
||||
if key.lower() not in ["host", "content-length"]
|
||||
}
|
||||
|
||||
# Make the request to the external service
|
||||
async with httpx.AsyncClient(timeout=60.0) as client:
|
||||
response = await client.request(
|
||||
method=request.method,
|
||||
url=external_url,
|
||||
params=request.query_params,
|
||||
headers=headers,
|
||||
content=body
|
||||
)
|
||||
|
||||
logger.debug("POI context proxy response",
|
||||
status_code=response.status_code,
|
||||
path=path)
|
||||
|
||||
# Return the response from the external service
|
||||
return JSONResponse(
|
||||
content=response.json() if response.text else None,
|
||||
status_code=response.status_code,
|
||||
headers=dict(response.headers)
|
||||
)
|
||||
|
||||
except httpx.RequestError as exc:
|
||||
logger.error("External service POI request failed",
|
||||
error=str(exc),
|
||||
path=path,
|
||||
external_url=external_url)
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
detail=f"POI service unavailable: {exc}"
|
||||
)
|
||||
except Exception as exc:
|
||||
logger.error("Unexpected error in POI proxy",
|
||||
error=str(exc),
|
||||
path=path)
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail="Internal server error in POI proxy"
|
||||
)
|
||||
Reference in New Issue
Block a user