69 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			69 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| 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):
 | ||
|     """全局异常处理器: 所有未捕获的异常都会在这里统一处理"""
 | ||
|     # 请求参数验证错误(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()
 | ||
|         )
 | ||
| 
 | ||
|     # 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()
 | ||
|         )
 | ||
| 
 | ||
|     # 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"},
 | ||
|         )
 | ||
| 
 | ||
|     # 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()
 | ||
|         )
 | ||
| 
 | ||
|     # 其他未知错误
 | ||
|     return JSONResponse(
 | ||
|         status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
 | ||
|         content=APIResponse(
 | ||
|             code=500,
 | ||
|             message=f"服务器内部错误: {str(exc)}",
 | ||
|             data=None
 | ||
|         ).model_dump()
 | ||
|     )
 |