from fastapi import Request, status from fastapi.responses import JSONResponse from fastapi.exceptions import HTTPException, RequestValidationError from mysql.connector import Error as MySQLError from jose import JWTError from schema.response_schema import APIResponse async def global_exception_handler(request: Request, exc: Exception): """全局异常处理器:所有未捕获的异常都会在这里统一处理""" # 1. 请求参数验证错误(Pydantic 校验失败) if isinstance(exc, RequestValidationError): error_details = [] for err in exc.errors(): error_details.append(f"{err['loc'][1]}: {err['msg']}") return JSONResponse( status_code=status.HTTP_400_BAD_REQUEST, content=APIResponse( code=400, message=f"请求参数错误:{'; '.join(error_details)}", data=None ).model_dump() ) # 2. HTTP 异常(主动抛出的业务错误、如 401/404) if isinstance(exc, HTTPException): return JSONResponse( status_code=exc.status_code, content=APIResponse( code=exc.status_code, message=exc.detail, data=None ).model_dump() ) # 3. JWT 相关错误(Token 无效/过期) if isinstance(exc, JWTError): return JSONResponse( status_code=status.HTTP_401_UNAUTHORIZED, content=APIResponse( code=401, message="Token 无效或已过期", data=None ).model_dump(), headers={"WWW-Authenticate": "Bearer"}, ) # 4. MySQL 数据库错误 if isinstance(exc, MySQLError): return JSONResponse( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, content=APIResponse( code=500, message=f"数据库错误:{str(exc)}", data=None ).model_dump() ) # 5. 其他未知错误(兜底处理) return JSONResponse( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, content=APIResponse( code=500, message=f"服务器内部错误:{str(exc)}", data=None ).model_dump() )