ChokePointAI / src /chokepoint /api /middleware.py
YuraBodnar's picture
feat(api): bootstrap FastAPI skeleton, DI stubs, Docker, CI/CD
6ca3a1d
Raw History Blame Contribute Delete
1.3 kB
"""Request-id + timing middleware.
Every response carries `X-Request-ID`; every request logs one JSON line
(method, path, status, duration) tagged with that id, per §9's
cross-cutting requirements.
"""
from __future__ import annotations
import time
import uuid
from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
from starlette.requests import Request
from starlette.responses import Response
from chokepoint.logging import get_logger
logger = get_logger("chokepoint.access")
class RequestContextMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) -> Response:
request_id = str(uuid.uuid4())
request.state.request_id = request_id
start = time.perf_counter()
response = await call_next(request)
duration_ms = round((time.perf_counter() - start) * 1000, 2)
response.headers["X-Request-ID"] = request_id
logger.info(
"request handled",
extra={
"request_id": request_id,
"method": request.method,
"path": request.url.path,
"status_code": response.status_code,
"duration_ms": duration_ms,
},
)
return response