From a26ec5e26808432357cf23505291ade34b396d74 Mon Sep 17 00:00:00 2001 From: Returner_org Date: Sun, 28 Jun 2026 15:13:33 +0300 Subject: [PATCH] =?UTF-8?q?feat(core):=20TraceMiddleware=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BF=D1=80=D0=BE=D0=B1=D1=80=D0=BE=D1=81=D0=B0=20X-T?= =?UTF-8?q?race-Id?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - читает X-Trace-Id из запроса или генерит новый ULID - кладёт trace_id в ContextVar на время запроса - возвращает X-Trace-Id в заголовке ответа --- src/elexam_core/middleware.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/elexam_core/middleware.py diff --git a/src/elexam_core/middleware.py b/src/elexam_core/middleware.py new file mode 100644 index 0000000..b004a18 --- /dev/null +++ b/src/elexam_core/middleware.py @@ -0,0 +1,24 @@ +from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint +from starlette.requests import Request +from starlette.responses import Response +from ulid import ULID + +from elexam_core.context import trace_id_context + + +TRACE_HEADER: str = "X-Trace-Id" + + +class TraceMiddleware(BaseHTTPMiddleware): + async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) -> Response: + header_trace_id = request.headers.get(TRACE_HEADER, default=None) + trace_id = header_trace_id or str(ULID()) + token = trace_id_context.set(trace_id) + + try: + response = await call_next(request) + finally: + trace_id_context.reset(token) + + response.headers[TRACE_HEADER] = trace_id + return response \ No newline at end of file