| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- """
- 全局异常处理器
- 类似Java的@ControllerAdvice,统一处理所有异常
- """
- from fastapi import Request, status
- from fastapi.responses import JSONResponse
- from fastapi.exceptions import RequestValidationError
- from starlette.exceptions import HTTPException as StarletteHTTPException
- from app.core.exceptions import (
- BaseAPIException,
- BusinessException,
- UnauthorizedException,
- ForbiddenException,
- NotFoundException,
- ValidationException,
- InternalServerException,
- StatusCode
- )
- from app.utils.logger_utils import logger
- async def base_api_exception_handler(request: Request, exc: BaseAPIException) -> JSONResponse:
- """
- 处理自定义API异常
- 返回统一的错误响应格式
- """
- logger.warning(
- f"API异常: {exc.detail} | "
- f"Status: {exc.status_code} | "
- f"Code: {exc.code} | "
- f"Path: {request.url.path}"
- )
-
- return JSONResponse(
- status_code=exc.status_code,
- content={
- "code": exc.code,
- "message": exc.detail,
- "data": None
- }
- )
- async def http_exception_handler(request: Request, exc: StarletteHTTPException) -> JSONResponse:
- """
- 处理FastAPI的HTTPException
- 转换为统一的响应格式
- """
- logger.warning(
- f"HTTP异常: {exc.detail} | "
- f"Status: {exc.status_code} | "
- f"Path: {request.url.path}"
- )
-
- # 根据状态码确定错误码
- error_code = exc.status_code
- if exc.status_code == 401:
- error_code = StatusCode.UNAUTHORIZED
- elif exc.status_code == 403:
- error_code = StatusCode.FORBIDDEN
- elif exc.status_code == 404:
- error_code = StatusCode.NOT_FOUND
- elif exc.status_code >= 500:
- error_code = StatusCode.INTERNAL_SERVER_ERROR
-
- return JSONResponse(
- status_code=exc.status_code,
- content={
- "code": error_code,
- "message": exc.detail,
- "data": None
- }
- )
- async def validation_exception_handler(request: Request, exc: RequestValidationError) -> JSONResponse:
- """
- 处理请求参数验证异常
- """
- errors = exc.errors()
- error_messages = []
- for error in errors:
- field = ".".join(str(loc) for loc in error.get("loc", []))
- msg = error.get("msg", "参数验证失败")
- error_messages.append(f"{field}: {msg}")
-
- detail = "; ".join(error_messages) if error_messages else "参数验证失败"
-
- logger.warning(
- f"参数验证失败: {detail} | "
- f"Path: {request.url.path}"
- )
-
- return JSONResponse(
- status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
- content={
- "code": StatusCode.BAD_REQUEST,
- "message": detail,
- "data": None
- }
- )
- async def general_exception_handler(request: Request, exc: Exception) -> JSONResponse:
- """
- 处理所有未捕获的异常
- 这是最后的异常处理兜底
- """
- logger.error(
- f"未处理的异常: {str(exc)} | "
- f"Type: {type(exc).__name__} | "
- f"Path: {request.url.path}",
- exc_info=True
- )
-
- # 检查异常消息中是否包含特定业务错误信息
- error_message = str(exc)
-
- # 权限相关错误
- if "无该货主权限" in error_message or "无权限" in error_message:
- return JSONResponse(
- status_code=403,
- content={
- "code": StatusCode.FORBIDDEN,
- "message": error_message if error_message else "无该货主权限!",
- "data": None
- }
- )
-
- # Token相关错误
- if "登录已过期" in error_message or "token" in error_message.lower() or "登录" in error_message:
- return JSONResponse(
- status_code=401,
- content={
- "code": StatusCode.INVALID_TOKEN,
- "message": error_message if error_message else "无效的登录信息",
- "data": None
- }
- )
-
- # 资源不存在
- if "不存在" in error_message or "not found" in error_message.lower():
- return JSONResponse(
- status_code=404,
- content={
- "code": StatusCode.NOT_FOUND,
- "message": error_message if error_message else "资源不存在",
- "data": None
- }
- )
-
- # 默认返回500错误
- return JSONResponse(
- status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
- content={
- "code": StatusCode.INTERNAL_SERVER_ERROR,
- "message": error_message if error_message else "服务器内部错误",
- "data": None
- }
- )
- def register_exception_handlers(app):
- """
- 注册所有异常处理器到FastAPI应用
- """
- # 自定义异常处理器(优先级最高)
- app.add_exception_handler(BaseAPIException, base_api_exception_handler)
- app.add_exception_handler(BusinessException, base_api_exception_handler)
- app.add_exception_handler(UnauthorizedException, base_api_exception_handler)
- app.add_exception_handler(ForbiddenException, base_api_exception_handler)
- app.add_exception_handler(NotFoundException, base_api_exception_handler)
- app.add_exception_handler(ValidationException, base_api_exception_handler)
- app.add_exception_handler(InternalServerException, base_api_exception_handler)
-
- # FastAPI的HTTPException
- app.add_exception_handler(StarletteHTTPException, http_exception_handler)
-
- # 请求验证异常
- app.add_exception_handler(RequestValidationError, validation_exception_handler)
-
- # 通用异常处理器(兜底,必须最后注册)
- app.add_exception_handler(Exception, general_exception_handler)
|