- uv(workspace) + pnpm monorepo;docker-compose(pg+api+web) - SQLAlchemy 16 MVP 表 + Alembic 初版迁移(无漂移,users stub) - FastAPI 骨架:统一错误信封(带 request_id) + structlog + /jobs/:id + OpenAPI - Next.js 骨架:纸感主题 token + OpenAPI→TS 客户端代码生成(gen:api) - CI(ruff/mypy/pytest + pg service + alembic 漂移校验) - 四份设计规格(PRODUCT/UX/ARCHITECTURE/DEV_PLAN) + CLAUDE.md
29 lines
910 B
Python
29 lines
910 B
Python
"""request_id 关联中间件(ARCH §9.3 / CLAUDE.md)。
|
||
|
||
每请求生成/透传 request_id,绑入 structlog contextvars,并回写响应头,
|
||
错误信封也带上同一 id,便于端到端 grep。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import uuid
|
||
from collections.abc import Awaitable, Callable
|
||
|
||
import structlog
|
||
from starlette.requests import Request
|
||
from starlette.responses import Response
|
||
|
||
REQUEST_ID_HEADER = "x-request-id"
|
||
|
||
|
||
async def request_id_middleware(
|
||
request: Request, call_next: Callable[[Request], Awaitable[Response]]
|
||
) -> Response:
|
||
request_id = request.headers.get(REQUEST_ID_HEADER) or uuid.uuid4().hex
|
||
structlog.contextvars.clear_contextvars()
|
||
structlog.contextvars.bind_contextvars(request_id=request_id)
|
||
request.state.request_id = request_id
|
||
response = await call_next(request)
|
||
response.headers[REQUEST_ID_HEADER] = request_id
|
||
return response
|