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() | |||
|  |     ) |