| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- import asyncio
- from fastapi import APIRouter, Depends, Query, Request, Response
- from sqlalchemy import text
- from sqlalchemy.orm import Session
- from core_domain import ServiceDescriptor, ServiceHealth
- from app.bootstrap.settings import ApiGatewaySettings
- from app.db.session import get_db
- from app.domain.repositories import GatewayRequestAuditRepository
- from app.infrastructure.proxy import ProxyServiceName, ProxyTarget, ServiceProxy
- from app.schemas.gateway import GatewayRequestAuditResponse, GatewayServicesHealthResponse
- router = APIRouter()
- @router.get("/health", response_model=ServiceDescriptor)
- def health_check(db: Session = Depends(get_db)) -> ServiceDescriptor:
- db.execute(text("SELECT 1"))
- return ServiceDescriptor(name="api-gateway")
- @router.get("/ready", response_model=ServiceHealth)
- def readiness_check(db: Session = Depends(get_db)) -> ServiceHealth:
- db.execute(text("SELECT 1"))
- return ServiceHealth(service="api-gateway", status="ok", database="ok")
- @router.get("/gateway/audits", response_model=list[GatewayRequestAuditResponse])
- def list_gateway_audits(
- tenant_id: str = Query(...),
- request_id: str | None = Query(default=None),
- target_service: str | None = Query(default=None),
- limit: int = Query(default=100, ge=1, le=500),
- db: Session = Depends(get_db),
- ) -> list[GatewayRequestAuditResponse]:
- items = GatewayRequestAuditRepository(db).list_by_scope(
- tenant_id=tenant_id,
- request_id=request_id,
- target_service=target_service,
- limit=limit,
- )
- return [GatewayRequestAuditResponse.from_entity(item) for item in items]
- def get_gateway_settings() -> ApiGatewaySettings:
- return ApiGatewaySettings()
- def get_service_proxy(settings: ApiGatewaySettings = Depends(get_gateway_settings)) -> ServiceProxy:
- return ServiceProxy(timeout_seconds=settings.proxy_timeout_seconds)
- def build_proxy_targets(settings: ApiGatewaySettings) -> dict[ProxyServiceName, ProxyTarget]:
- return {
- "workflow-service": ProxyTarget(
- service_name="workflow-service",
- base_url=settings.workflow_service_url,
- path_prefix="/workflows",
- health_path="/workflows/health",
- ),
- "session-service": ProxyTarget(
- service_name="session-service",
- base_url=settings.session_service_url,
- path_prefix="/sessions",
- health_path="/sessions/health",
- ),
- "runtime-service": ProxyTarget(
- service_name="runtime-service",
- base_url=settings.runtime_service_url,
- path_prefix="/runtime",
- health_path="/runtime/health",
- ),
- "tool-service": ProxyTarget(
- service_name="tool-service",
- base_url=settings.tool_service_url,
- path_prefix="/tools",
- health_path="/tools/health",
- ),
- "model-gateway-service": ProxyTarget(
- service_name="model-gateway-service",
- base_url=settings.model_gateway_service_url,
- path_prefix="/models",
- health_path="/models/health",
- ),
- "code-runner-service": ProxyTarget(
- service_name="code-runner-service",
- base_url=settings.code_runner_service_url,
- path_prefix="/code",
- health_path="/code/health",
- ),
- }
- @router.get("/gateway/services/health", response_model=GatewayServicesHealthResponse)
- async def downstream_health_check(
- settings: ApiGatewaySettings = Depends(get_gateway_settings),
- ) -> GatewayServicesHealthResponse:
- targets = build_proxy_targets(settings)
- health_proxy = ServiceProxy(timeout_seconds=settings.downstream_health_timeout_seconds)
- downstream_services = await asyncio.gather(
- *[health_proxy.check_health(target) for target in targets.values()]
- )
- status = "ok" if all(item.status == "ok" for item in downstream_services) else "degraded"
- return GatewayServicesHealthResponse(
- status=status,
- downstream_services=downstream_services,
- )
- @router.api_route(
- "/gateway/workflows",
- methods=["GET", "POST", "PUT", "PATCH", "DELETE"],
- )
- @router.api_route(
- "/gateway/workflows/{path:path}",
- methods=["GET", "POST", "PUT", "PATCH", "DELETE"],
- )
- async def proxy_workflow_service(
- request: Request,
- path: str = "",
- settings: ApiGatewaySettings = Depends(get_gateway_settings),
- proxy: ServiceProxy = Depends(get_service_proxy),
- ) -> Response:
- return await proxy.forward(
- request=request,
- target=build_proxy_targets(settings)["workflow-service"],
- path=path,
- )
- @router.api_route(
- "/gateway/sessions",
- methods=["GET", "POST", "PUT", "PATCH", "DELETE"],
- )
- @router.api_route(
- "/gateway/sessions/{path:path}",
- methods=["GET", "POST", "PUT", "PATCH", "DELETE"],
- )
- async def proxy_session_service(
- request: Request,
- path: str = "",
- settings: ApiGatewaySettings = Depends(get_gateway_settings),
- proxy: ServiceProxy = Depends(get_service_proxy),
- ) -> Response:
- return await proxy.forward(
- request=request,
- target=build_proxy_targets(settings)["session-service"],
- path=path,
- )
- @router.api_route(
- "/gateway/runtime",
- methods=["GET", "POST", "PUT", "PATCH", "DELETE"],
- )
- @router.api_route(
- "/gateway/runtime/{path:path}",
- methods=["GET", "POST", "PUT", "PATCH", "DELETE"],
- )
- async def proxy_runtime_service(
- request: Request,
- path: str = "",
- settings: ApiGatewaySettings = Depends(get_gateway_settings),
- proxy: ServiceProxy = Depends(get_service_proxy),
- ) -> Response:
- return await proxy.forward(
- request=request,
- target=build_proxy_targets(settings)["runtime-service"],
- path=path,
- )
- @router.api_route(
- "/gateway/tools",
- methods=["GET", "POST", "PUT", "PATCH", "DELETE"],
- )
- @router.api_route(
- "/gateway/tools/{path:path}",
- methods=["GET", "POST", "PUT", "PATCH", "DELETE"],
- )
- async def proxy_tool_service(
- request: Request,
- path: str = "",
- settings: ApiGatewaySettings = Depends(get_gateway_settings),
- proxy: ServiceProxy = Depends(get_service_proxy),
- ) -> Response:
- return await proxy.forward(
- request=request,
- target=build_proxy_targets(settings)["tool-service"],
- path=path,
- )
- @router.api_route(
- "/gateway/models",
- methods=["GET", "POST", "PUT", "PATCH", "DELETE"],
- )
- @router.api_route(
- "/gateway/models/{path:path}",
- methods=["GET", "POST", "PUT", "PATCH", "DELETE"],
- )
- async def proxy_model_gateway_service(
- request: Request,
- path: str = "",
- settings: ApiGatewaySettings = Depends(get_gateway_settings),
- proxy: ServiceProxy = Depends(get_service_proxy),
- ) -> Response:
- return await proxy.forward(
- request=request,
- target=build_proxy_targets(settings)["model-gateway-service"],
- path=path,
- )
- @router.api_route(
- "/gateway/code",
- methods=["GET", "POST", "PUT", "PATCH", "DELETE"],
- )
- @router.api_route(
- "/gateway/code/{path:path}",
- methods=["GET", "POST", "PUT", "PATCH", "DELETE"],
- )
- async def proxy_code_runner_service(
- request: Request,
- path: str = "",
- settings: ApiGatewaySettings = Depends(get_gateway_settings),
- proxy: ServiceProxy = Depends(get_service_proxy),
- ) -> Response:
- return await proxy.forward(
- request=request,
- target=build_proxy_targets(settings)["code-runner-service"],
- path=path,
- )
|