Spaces:
Sleeping
Sleeping
| """Global error handling middleware.""" | |
| from fastapi import Request, HTTPException | |
| from fastapi.responses import JSONResponse | |
| from fastapi.exceptions import RequestValidationError | |
| from starlette.exceptions import HTTPException as StarletteHTTPException | |
| import logging | |
| import traceback | |
| import re | |
| logger = logging.getLogger(__name__) | |
| def redact_sensitive_data(data: str) -> str: | |
| """Redact sensitive information from logs.""" | |
| # Redact Authorization headers | |
| data = re.sub(r'(Authorization["\']?:\s*["\']?Bearer\s+)[^\s"\']+', r'\1***', data, flags=re.IGNORECASE) | |
| # Redact bearer tokens in any form | |
| data = re.sub(r'(bearer["\']?:\s*["\']?)[^\s"\']+', r'\1***', data, flags=re.IGNORECASE) | |
| # Redact JWT tokens (3 base64 parts separated by dots) | |
| data = re.sub(r'\b[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b', '***JWT***', data) | |
| return data | |
| async def http_exception_handler(request: Request, exc: HTTPException): | |
| """Handle HTTP exceptions.""" | |
| return JSONResponse( | |
| status_code=exc.status_code, | |
| content={ | |
| "error": exc.detail, | |
| "code": f"HTTP_{exc.status_code}" | |
| } | |
| ) | |
| async def validation_exception_handler(request: Request, exc: RequestValidationError): | |
| """Handle validation errors.""" | |
| errors = [] | |
| for error in exc.errors(): | |
| field = ".".join(str(x) for x in error["loc"]) | |
| errors.append(f"{field}: {error['msg']}") | |
| return JSONResponse( | |
| status_code=422, | |
| content={ | |
| "error": "Validation failed", | |
| "details": "; ".join(errors), | |
| "code": "VALIDATION_ERROR" | |
| } | |
| ) | |
| async def general_exception_handler(request: Request, exc: Exception): | |
| """Handle unexpected exceptions.""" | |
| # Redact sensitive data from error messages and traceback | |
| error_msg = redact_sensitive_data(str(exc)) | |
| sanitized_traceback = redact_sensitive_data(traceback.format_exc()) | |
| logger.error(f"Unexpected error: {error_msg}\n{sanitized_traceback}") | |
| return JSONResponse( | |
| status_code=500, | |
| content={ | |
| "error": "Internal server error", | |
| "details": "An unexpected error occurred", | |
| "code": "INTERNAL_ERROR" | |
| } | |
| ) | |
| def register_exception_handlers(app): | |
| """Register all exception handlers with the app.""" | |
| app.add_exception_handler(HTTPException, http_exception_handler) | |
| app.add_exception_handler(RequestValidationError, validation_exception_handler) | |
| app.add_exception_handler(Exception, general_exception_handler) |