52 lines
1.9 KiB
Python
52 lines
1.9 KiB
Python
|
|
"""
|
||
|
|
Lightweight Error Handling Middleware
|
||
|
|
"""
|
||
|
|
|
||
|
|
from fastapi import Request, HTTPException
|
||
|
|
from fastapi.responses import JSONResponse
|
||
|
|
from starlette.middleware.base import BaseHTTPMiddleware
|
||
|
|
|
||
|
|
from .error_handler import StructuredLogger, ErrorCategory, ErrorCode, create_error_response
|
||
|
|
|
||
|
|
|
||
|
|
class ErrorMiddleware(BaseHTTPMiddleware):
|
||
|
|
"""Concise error handling middleware following DRY principles"""
|
||
|
|
|
||
|
|
def __init__(self, app):
|
||
|
|
super().__init__(app)
|
||
|
|
self.logger = StructuredLogger(__name__)
|
||
|
|
|
||
|
|
async def dispatch(self, request: Request, call_next):
|
||
|
|
try:
|
||
|
|
return await call_next(request)
|
||
|
|
except HTTPException as e:
|
||
|
|
# HTTP exceptions - map to appropriate categories
|
||
|
|
category = ErrorCategory.VALIDATION if e.status_code < 500 else ErrorCategory.INTERNAL
|
||
|
|
error_code = ErrorCode.INVALID_REQUEST if e.status_code < 500 else ErrorCode.INTERNAL_ERROR
|
||
|
|
|
||
|
|
self.logger.error(
|
||
|
|
f"HTTP {e.status_code}: {e.detail}",
|
||
|
|
category=category,
|
||
|
|
error_code=error_code,
|
||
|
|
extra={"path": str(request.url), "method": request.method}
|
||
|
|
)
|
||
|
|
|
||
|
|
return JSONResponse(
|
||
|
|
status_code=e.status_code,
|
||
|
|
content=create_error_response(category, error_code, e.detail)
|
||
|
|
)
|
||
|
|
except Exception as e:
|
||
|
|
# Unexpected errors
|
||
|
|
self.logger.error(
|
||
|
|
f"Unhandled error: {str(e)}",
|
||
|
|
error=e,
|
||
|
|
category=ErrorCategory.INTERNAL,
|
||
|
|
error_code=ErrorCode.INTERNAL_ERROR,
|
||
|
|
extra={"path": str(request.url), "method": request.method}
|
||
|
|
)
|
||
|
|
|
||
|
|
return JSONResponse(
|
||
|
|
status_code=500,
|
||
|
|
content=create_error_response(ErrorCategory.INTERNAL, ErrorCode.INTERNAL_ERROR)
|
||
|
|
)
|