77 lines
2.4 KiB
Python
77 lines
2.4 KiB
Python
# pxy_routing/api/views.py
|
|
from __future__ import annotations
|
|
import uuid
|
|
from rest_framework.decorators import api_view, throttle_classes
|
|
from rest_framework.response import Response
|
|
from rest_framework import status
|
|
from rest_framework.throttling import ScopedRateThrottle
|
|
|
|
from pxy_routing.services.factory import get_routing_provider
|
|
|
|
def _err(code: str, message: str, hint: str | None = None, http_status: int = 400):
|
|
return Response(
|
|
{
|
|
"ok": False,
|
|
"code": code,
|
|
"message": message,
|
|
"hint": hint,
|
|
"trace_id": str(uuid.uuid4()),
|
|
},
|
|
status=http_status,
|
|
)
|
|
|
|
@api_view(["GET"])
|
|
@throttle_classes([ScopedRateThrottle])
|
|
def routing_health(request):
|
|
routing_health.throttle_scope = "routing_health" # DRF scoped throttle
|
|
provider = get_routing_provider()
|
|
try:
|
|
info = provider.health() or {}
|
|
ok = bool(info.get("ok", False))
|
|
return Response(
|
|
{
|
|
"ok": ok,
|
|
"provider": info.get("provider"),
|
|
**info, # includes base_url/profile/reason
|
|
}
|
|
)
|
|
except Exception as e:
|
|
return _err(
|
|
code="routing_health_error",
|
|
message="Routing health check failed",
|
|
hint=str(e),
|
|
http_status=status.HTTP_502_BAD_GATEWAY,
|
|
)
|
|
|
|
@api_view(["POST"])
|
|
@throttle_classes([ScopedRateThrottle])
|
|
def routing_isochrone(request):
|
|
routing_isochrone.throttle_scope = "routing_isochrone" # DRF scoped throttle
|
|
data = request.data or {}
|
|
center = data.get("center")
|
|
minutes = data.get("minutes")
|
|
|
|
if not isinstance(center, (list, tuple)) or len(center) != 2:
|
|
return _err("invalid", "center must be [lat, lon]", http_status=status.HTTP_400_BAD_REQUEST)
|
|
try:
|
|
minutes = int(minutes)
|
|
except Exception:
|
|
return _err("invalid", "minutes must be an integer", http_status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
provider = get_routing_provider()
|
|
try:
|
|
feat = provider.isochrone(tuple(center), minutes)
|
|
return Response(feat)
|
|
except Exception as e:
|
|
# Map to a consistent envelope for upstream/provider issues
|
|
return _err(
|
|
code="routing_error",
|
|
message="Failed to compute isochrone",
|
|
hint=str(e),
|
|
http_status=status.HTTP_502_BAD_GATEWAY,
|
|
)
|
|
|
|
# Backward-compatible aliases expected by urls.py
|
|
health = routing_health
|
|
isochrone = routing_isochrone
|