69 lines
2.3 KiB
Python
69 lines
2.3 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):
|
||
"""全局异常处理器:所有未捕获的异常都会在这里统一处理"""
|
||
# 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()
|
||
)
|