| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- from typing import Any
- from fastapi import FastAPI, Request, status
- from fastapi.exceptions import RequestValidationError, ResponseValidationError
- from pydantic_validation_decorator import FieldValidationError
- from sqlalchemy.exc import SQLAlchemyError
- from starlette.exceptions import HTTPException
- from starlette.responses import JSONResponse
- from app.common.constant import RET
- from app.common.response import ErrorResponse
- from app.core.logger import log
- class CustomException(Exception):
- """
- 自定义异常基类
- """
- def __init__(
- self,
- msg: str = RET.EXCEPTION.msg,
- code: int = RET.EXCEPTION.code,
- status_code: int = status.HTTP_500_INTERNAL_SERVER_ERROR,
- data: Any | None = None,
- success: bool = False,
- ) -> None:
- """
- 初始化异常对象。
- 参数:
- - msg (str): 错误消息。
- - code (int): 业务状态码。
- - status_code (int): HTTP 状态码。
- - data (Any | None): 附加数据。
- - success (bool): 是否成功标记,默认 False。
- 返回:
- - None
- """
- super().__init__(msg) # 调用父类初始化方法
- self.status_code = status_code
- self.code = code
- self.msg = msg
- self.data = data
- self.success = success
- def __str__(self) -> str:
- """返回异常消息
- 返回:
- - str: 异常消息
- """
- return self.msg
- def handle_exception(app: FastAPI) -> None:
- """
- 注册全局异常处理器。
- 参数:
- - app (FastAPI): 应用实例。
- 返回:
- - None
- """
- @app.exception_handler(CustomException)
- async def CustomExceptionHandler(request: Request, exc: CustomException) -> JSONResponse:
- """
- 自定义异常处理器
- 参数:
- - request (Request): 请求对象。
- - exc (CustomException): 自定义异常实例。
- 返回:
- - JSONResponse: 包含错误信息的 JSON 响应。
- """
- log.opt(exception=False).error(
- "[自定义异常] {} {} | 错误码: {} | 错误信息: {}",
- request.method,
- request.url.path,
- exc.code,
- exc.msg
- )
- return ErrorResponse(
- msg=exc.msg,
- code=exc.code,
- status_code=exc.status_code,
- data=exc.data,
- )
- @app.exception_handler(HTTPException)
- async def HttpExceptionHandler(request: Request, exc: HTTPException) -> JSONResponse:
- """
- HTTP异常处理器
- 参数:
- - request (Request): 请求对象。
- - exc (HTTPException): HTTP异常实例。
- 返回:
- - JSONResponse: 包含错误信息的 JSON 响应。
- """
- log.opt(exception=False).error(
- "[HTTP异常] {} {} | 错误信息: {}",
- request.method,
- request.url.path,
- str(exc)
- )
- return ErrorResponse(msg=exc.detail or "请求错误", status_code=exc.status_code)
- @app.exception_handler(RequestValidationError)
- async def ValidationExceptionHandler(
- request: Request, exc: RequestValidationError
- ) -> JSONResponse:
- """
- 请求参数验证异常处理器
- 参数:
- - request (Request): 请求对象。
- - exc (RequestValidationError): 请求参数验证异常实例。
- 返回:
- - JSONResponse: 包含错误信息的 JSON 响应。
- """
- error_mapping = {
- "Field required": "请求失败,缺少必填项!",
- "value is not a valid list": "类型错误,提交参数应该为列表!",
- "value is not a valid int": "类型错误,提交参数应该为整数!",
- "value could not be parsed to a boolean": "类型错误,提交参数应该为布尔值!",
- "Input should be a valid list": "类型错误,输入应该是一个有效的列表!",
- }
- raw_msg = exc.errors()[0].get("msg")
- msg = error_mapping.get(raw_msg, raw_msg)
- # 去掉Pydantic默认的前缀“Value error”, 仅保留具体提示内容
- if isinstance(msg, str) and msg.startswith("Value error"):
- msg = (
- msg.split(",", 1)[1].strip()
- if "," in msg
- else msg.replace("Value error", "").strip()
- )
- log.opt(exception=False).error(
- "[参数验证异常] {} {} | 错误信息: {}",
- request.method,
- request.url.path,
- str(exc),
- )
- return ErrorResponse(
- msg=str(msg),
- status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
- data=exc.body,
- )
- @app.exception_handler(ResponseValidationError)
- async def ResponseValidationHandle(
- request: Request, exc: ResponseValidationError
- ) -> JSONResponse:
- """
- 响应参数验证异常处理器
- 参数:
- - request (Request): 请求对象。
- - exc (ResponseValidationError): 响应参数验证异常实例。
- 返回:
- - JSONResponse: 包含错误信息的 JSON 响应。
- """
- log.opt(exception=True).error(
- "[响应验证异常] {} {} | 错误信息: 响应数据格式错误",
- request.method,
- request.url.path,
- )
- return ErrorResponse(
- msg="服务器响应格式错误",
- status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
- data=exc.body,
- )
- @app.exception_handler(SQLAlchemyError)
- async def SQLAlchemyExceptionHandler(request: Request, exc: SQLAlchemyError) -> JSONResponse:
- """
- 数据库异常处理器
- 参数:
- - request (Request): 请求对象。
- - exc (SQLAlchemyError): 数据库异常实例。
- 返回:
- - JSONResponse: 包含错误信息的 JSON 响应。
- """
- error_msg = "数据库操作失败"
- exc_type = type(exc).__name__
- # 对于生产环境,返回通用错误消息
- log.opt(exception=True).error(
- "[数据库异常] {} {} | 错误类型: {}",
- request.method,
- request.url.path,
- exc_type
- )
- return ErrorResponse(
- msg=f"{error_msg}: {exc_type}",
- status_code=status.HTTP_400_BAD_REQUEST,
- data=str(exc),
- )
- @app.exception_handler(ValueError)
- async def ValueExceptionHandler(request: Request, exc: ValueError) -> JSONResponse:
- """
- 值异常处理器
- 参数:
- - request (Request): 请求对象。
- - exc (ValueError): 值异常实例。
- 返回:
- - JSONResponse: 包含错误信息的 JSON 响应。
- """
- log.opt(exception=False).error("[值异常] {} {} | 错误信息: {}", request.method, request.url.path, str(exc))
- return ErrorResponse(msg=str(exc), status_code=status.HTTP_400_BAD_REQUEST)
- @app.exception_handler(FieldValidationError)
- async def FieldValidationExceptionHandler(
- request: Request, exc: FieldValidationError
- ) -> JSONResponse:
- """
- 字段验证异常处理器
- 参数:
- - request (Request): 请求对象。
- - exc (FieldValidationError): 字段验证异常实例。
- 返回:
- - JSONResponse: 包含错误信息的 JSON 响应。
- """
- log.opt(exception=False).error("[字段验证异常] {} {} | 错误信息: {}",
- request.method, request.url.path, exc.message)
- return ErrorResponse(msg=exc.message or "字段验证异常", status_code=status.HTTP_422_UNPROCESSABLE_ENTITY)
- @app.exception_handler(Exception)
- async def AllExceptionHandler(request: Request, exc: Exception) -> JSONResponse:
- """
- 全局异常处理器
- 参数:
- - request (Request): 请求对象。
- - exc (Exception): 异常实例。
- 返回:
- - JSONResponse: 包含错误信息的 JSON 响应。
- """
- exc_type = type(exc).__name__
- log.opt(exception=False).error(
- "[未捕获异常] {} {} | 错误类型: {} | 错误信息: {}",
- request.method,
- request.url.path,
- exc_type,
- str(exc)
- )
- # 对于未捕获的异常,返回通用错误信息
- return ErrorResponse(
- msg="服务器内部错误",
- status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
- data=None,
- )
|