From 2d354bfde6471f61eee0c478b2d28431b02cdceb Mon Sep 17 00:00:00 2001 From: Matteo Benedetto Date: Sun, 16 Aug 2026 19:32:29 +0200 Subject: [PATCH] feat: X-Request-ID per richiesta (header risposta + audit log) - middleware: genera o accetta X-Request-ID, lo restituisce in header - contextvar letto da _audit: correlazione richieste nei log - verificato sul server: header + audit correlati (istanza di test) --- gateway/main.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/gateway/main.py b/gateway/main.py index c8b8755..122714b 100644 --- a/gateway/main.py +++ b/gateway/main.py @@ -19,6 +19,7 @@ Endpoints: from __future__ import annotations import asyncio +import contextvars import hashlib import json import logging @@ -91,6 +92,18 @@ async def lifespan(_app: FastAPI): app = FastAPI(title="Memory Gateway", version="2.5.0", lifespan=lifespan) qdrant = QdrantClient(url=QDRANT_URL, api_key=QDRANT_API_KEY) +# Request ID: generato per richiesta, loggato nell'audit e restituito in header +_request_id: contextvars.ContextVar[str] = contextvars.ContextVar("request_id", default="-") + + +@app.middleware("http") +async def request_id_middleware(request: Request, call_next): + rid = request.headers.get("X-Request-ID") or str(uuid.uuid4()) + _request_id.set(rid) + response = await call_next(request) + response.headers["X-Request-ID"] = rid + return response + # Rate limit in-memory: {key: [timestamps]} _ratelimit: dict[str, list[float]] = {} @@ -184,6 +197,7 @@ def _audit(key: str, action: str, **extra: Any) -> None: "ts": datetime.now(timezone.utc).isoformat(), "key": key[:8] + "...", "action": action, + "request_id": _request_id.get(), **extra, } log.info(json.dumps(entry, default=str))