""" 全局异常处理和错误响应 """ import logging from fastapi import Request, status from fastapi.exceptions import RequestValidationError from fastapi.responses import JSONResponse from starlette.exceptions import HTTPException as StarletteHTTPException logger = logging.getLogger(__name__) class APIException(Exception): """API 异常基类""" def __init__( self, message: str, status_code: int = status.HTTP_400_BAD_REQUEST, error_code: str = "API_ERROR", ): self.message = message self.status_code = status_code self.error_code = error_code super().__init__(message) class AuthenticationError(APIException): """认证错误""" def __init__(self, message: str = "Authentication failed"): super().__init__( message=message, status_code=status.HTTP_401_UNAUTHORIZED, error_code="AUTH_ERROR", ) class PermissionDeniedError(APIException): """权限拒绝""" def __init__(self, message: str = "Permission denied"): super().__init__( message=message, status_code=status.HTTP_403_FORBIDDEN, error_code="PERMISSION_DENIED", ) class ResourceNotFoundError(APIException): """资源不存在""" def __init__(self, resource: str = "Resource"): super().__init__( message=f"{resource} not found", status_code=status.HTTP_404_NOT_FOUND, error_code="NOT_FOUND", ) class ValidationError(APIException): """验证错误""" def __init__(self, message: str): super().__init__( message=message, status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, error_code="VALIDATION_ERROR", ) async def api_exception_handler(request: Request, exc: APIException): """API 异常处理""" return JSONResponse( status_code=exc.status_code, content={ "error": { "code": exc.error_code, "message": exc.message, } }, ) async def http_exception_handler(request: Request, exc: StarletteHTTPException): """HTTP 异常处理""" return JSONResponse( status_code=exc.status_code, content={ "error": { "code": f"HTTP_{exc.status_code}", "message": exc.detail, } }, ) async def validation_exception_handler(request: Request, exc: RequestValidationError): """请求验证异常处理""" errors = [] for error in exc.errors(): errors.append( { "field": ".".join(str(loc) for loc in error["loc"]), "message": error["msg"], "type": error["type"], } ) return JSONResponse( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, content={ "error": { "code": "VALIDATION_ERROR", "message": "Request validation failed", "details": errors, } }, ) async def general_exception_handler(request: Request, exc: Exception): """通用异常处理""" logger.error(f"Unhandled exception: {exc}", exc_info=True) # 生产环境不返回详细错误信息 return JSONResponse( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, content={ "error": { "code": "INTERNAL_ERROR", "message": "An internal error occurred", # "detail": str(exc), # 仅在开发环境启用 } }, )