Include Loyalty/Communication/Sports Center backends and registry updates alongside production nginx and compose wiring. Co-authored-by: Cursor <cursoragent@cursor.com>
34 lines
1.2 KiB
Python
34 lines
1.2 KiB
Python
"""Tenant header resolution middleware."""
|
|
from __future__ import annotations
|
|
|
|
from uuid import UUID
|
|
|
|
from starlette.middleware.base import BaseHTTPMiddleware
|
|
from starlette.requests import Request
|
|
from starlette.responses import JSONResponse, Response
|
|
|
|
from shared.responses import ErrorDetail, ErrorResponse
|
|
from shared.tenant import HEADER_TENANT_ID, STATE_TENANT_ID
|
|
|
|
|
|
class TenantHeaderMiddleware(BaseHTTPMiddleware):
|
|
"""Resolve tenant from X-Tenant-ID header only (microservice pattern)."""
|
|
|
|
async def dispatch(self, request: Request, call_next) -> Response:
|
|
setattr(request.state, STATE_TENANT_ID, None)
|
|
raw = request.headers.get(HEADER_TENANT_ID)
|
|
if raw:
|
|
try:
|
|
setattr(request.state, STATE_TENANT_ID, UUID(raw))
|
|
except ValueError:
|
|
return JSONResponse(
|
|
status_code=400,
|
|
content=ErrorResponse(
|
|
error=ErrorDetail(
|
|
code="invalid_tenant_id",
|
|
message="مقدار هدر X-Tenant-ID نامعتبر است",
|
|
)
|
|
).model_dump(),
|
|
)
|
|
return await call_next(request)
|