|
1 | 1 | from fastapi import HTTPException, Request, Response, status |
| 2 | +from fastapi.exception_handlers import http_exception_handler as default_http_handler |
2 | 3 | from fastapi.responses import ORJSONResponse |
3 | 4 | from fastapi.routing import APIRoute |
4 | 5 | from sqlalchemy import select |
@@ -39,27 +40,20 @@ def generic_exception_handler(request: Request, exc: Exception) -> Response: |
39 | 40 | ) |
40 | 41 |
|
41 | 42 |
|
42 | | -def http_exception_handler(request: Request, exc: Exception) -> Response: |
| 43 | +async def http_exception_handler(request: Request, exc: Exception) -> Response: |
43 | 44 | """Log HTTP exceptions with tenant context for observability.""" |
44 | | - if not isinstance(exc, HTTPException): |
45 | | - return ORJSONResponse( |
46 | | - status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, |
47 | | - content={"detail": str(exc)}, |
48 | | - ) |
| 45 | + http_exc = exc if isinstance(exc, HTTPException) else HTTPException(500, str(exc)) |
49 | 46 | role = ctx_role.get() |
50 | | - log_method = logger.warning if exc.status_code < 500 else logger.error |
| 47 | + log_method = logger.warning if http_exc.status_code < 500 else logger.error |
51 | 48 | log_method( |
52 | 49 | "HTTP error", |
53 | | - status_code=exc.status_code, |
54 | | - detail=exc.detail, |
| 50 | + status_code=http_exc.status_code, |
| 51 | + detail=http_exc.detail, |
55 | 52 | path=request.url.path, |
56 | 53 | method=request.method, |
57 | 54 | role=role, |
58 | 55 | ) |
59 | | - return ORJSONResponse( |
60 | | - status_code=exc.status_code, |
61 | | - content={"detail": exc.detail}, |
62 | | - ) |
| 56 | + return await default_http_handler(request, http_exc) |
63 | 57 |
|
64 | 58 |
|
65 | 59 | def bootstrap_role(organization_id: OrganizationID | None = None) -> Role: |
|
0 commit comments