File size: 1,634 Bytes
dbc1e7d 3187428 dbc1e7d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | """
Global error handler.
Catches unhandled exceptions and returns sanitized JSON responses.
Never leaks stack traces, file paths, or internal state to the client.
Logs the full traceback server-side for debugging.
For a mental health platform: error messages must be gentle and reassuring.
"""
import logging
from uuid import uuid4
from fastapi import Request
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware
logger = logging.getLogger(__name__)
class ErrorHandlerMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
request_id = request.headers.get("X-Request-ID", str(uuid4())[:8])
try:
response = await call_next(request)
# Attach request ID to response headers for tracing
response.headers["X-Request-ID"] = request_id
return response
except Exception as exc:
# Log the full traceback server-side
logger.error(
f"Unhandled exception [request_id={request_id}] {request.method} {request.url.path}: {exc}",
exc_info=True,
)
# Return sanitized response — NEVER expose internals
return JSONResponse(
status_code=500,
content={
"error": {
"message": "Something went wrong on our end. Your data is safe. Please try again in a moment.",
"request_id": request_id,
}
},
headers={"X-Request-ID": request_id},
)
|