""" 全局异常处理器 处理各类异常并返回统一格式的错误响应 需求: 7.3, 8.1, 8.2, 8.3, 8.4 """ import logging from fastapi import Request, FastAPI, HTTPException from fastapi.responses import JSONResponse from fastapi.exceptions import RequestValidationError from sqlalchemy.exc import SQLAlchemyError logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) def register_exception_handlers(app: FastAPI): """注册全局异常处理器""" @app.exception_handler(HTTPException) async def http_exception_handler(request: Request, exc: HTTPException): """HTTP异常处理""" logger.warning(f"HTTP error {exc.status_code}: {exc.detail}") if isinstance(exc.detail, dict): payload = {"data": None} payload.update(exc.detail) else: payload = { "code": exc.status_code, "message": exc.detail, "detail": exc.detail, "data": None } return JSONResponse( status_code=exc.status_code, content=payload ) @app.exception_handler(RequestValidationError) async def validation_exception_handler(request: Request, exc: RequestValidationError): """参数验证错误处理""" errors = exc.errors() logger.warning(f"Validation error: {errors}") # 提取第一条错误的友好提示,避免将原始列表暴露给前端 if errors: first_error = errors[0] message = first_error.get("msg", "请求参数错误") # 去掉 Pydantic 自动添加的 "Value error, " 前缀 if message.startswith("Value error, "): message = message[len("Value error, "):] else: message = "请求参数错误" return JSONResponse( status_code=400, content={"code": 400, "message": message, "data": None} ) @app.exception_handler(SQLAlchemyError) async def database_exception_handler(request: Request, exc: SQLAlchemyError): """数据库错误处理""" logger.error(f"Database error: {exc}") return JSONResponse( status_code=500, content={"code": 500, "message": "Database error", "data": None} ) @app.exception_handler(Exception) async def global_exception_handler(request: Request, exc: Exception): """全局异常处理""" logger.error(f"Unhandled exception: {exc}") return JSONResponse( status_code=500, content={"code": 500, "message": "Internal server error", "data": None} )