from fastapi import FastAPI, Request, status from fastapi.responses import JSONResponse from fastapi.exceptions import RequestValidationError from starlette.exceptions import HTTPException as StarletteHTTPException import logging from typing import Any, Dict, Optional, Union from app.utils.response import APIResponse logger = logging.getLogger(__name__) class CustomHTTPException(Exception): """自定义HTTP异常""" def __init__( self, status_code: int = 400, code: int = None, message: str = "操作失败", data: Any = None ): self.status_code = status_code self.code = code or status_code self.message = message self.data = data super().__init__(self.message) def setup_exception_handlers(app: FastAPI) -> None: """设置FastAPI应用的异常处理程序""" @app.exception_handler(CustomHTTPException) async def custom_http_exception_handler(request: Request, exc: CustomHTTPException): """处理自定义HTTP异常""" logger.error(f"自定义HTTP异常: {exc.message} (状态码: {exc.status_code}, 业务码: {exc.code})") return JSONResponse( status_code=exc.status_code, content=APIResponse.error( message=exc.message, code=exc.code, data=exc.data ) ) @app.exception_handler(StarletteHTTPException) async def http_exception_handler(request: Request, exc: StarletteHTTPException): """处理标准HTTP异常""" logger.error(f"HTTP异常: {exc.detail} (状态码: {exc.status_code})") return JSONResponse( status_code=exc.status_code, content=APIResponse.error( message=str(exc.detail), code=exc.status_code ) ) @app.exception_handler(RequestValidationError) async def validation_exception_handler(request: Request, exc: RequestValidationError): """处理请求验证异常""" error_details = exc.errors() error_messages = [] for error in error_details: location = " -> ".join(str(loc) for loc in error["loc"]) message = f"{location}: {error['msg']}" error_messages.append(message) error_message = "; ".join(error_messages) logger.error(f"验证错误: {error_message}") return JSONResponse( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, content=APIResponse.error( message="请求参数验证失败", code=status.HTTP_422_UNPROCESSABLE_ENTITY, data={"details": error_details} ) ) @app.exception_handler(Exception) async def general_exception_handler(request: Request, exc: Exception): """处理通用异常""" logger.exception(f"未处理的异常: {str(exc)}") return JSONResponse( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, content=APIResponse.error( message="服务器内部错误", code=status.HTTP_500_INTERNAL_SERVER_ERROR, data={"detail": str(exc)} if app.debug else None ) )