90 lines
3.2 KiB
Python
90 lines
3.2 KiB
Python
from fastapi import FastAPI, Request, status
|
|
from fastapi.responses import JSONResponse
|
|
from fastapi.exceptions import RequestValidationError
|
|
from starlette.exceptions import HTTPException as StarletteHTTPException
|
|
import logging
|
|
from typing import Any, Dict, Optional, Union
|
|
|
|
from app.utils.response import APIResponse
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class CustomHTTPException(Exception):
|
|
"""自定义HTTP异常"""
|
|
|
|
def __init__(
|
|
self,
|
|
status_code: int = 400,
|
|
code: int = None,
|
|
message: str = "操作失败",
|
|
data: Any = None
|
|
):
|
|
self.status_code = status_code
|
|
self.code = code or status_code
|
|
self.message = message
|
|
self.data = data
|
|
super().__init__(self.message)
|
|
|
|
def setup_exception_handlers(app: FastAPI) -> None:
|
|
"""设置FastAPI应用的异常处理程序"""
|
|
|
|
@app.exception_handler(CustomHTTPException)
|
|
async def custom_http_exception_handler(request: Request, exc: CustomHTTPException):
|
|
"""处理自定义HTTP异常"""
|
|
logger.error(f"自定义HTTP异常: {exc.message} (状态码: {exc.status_code}, 业务码: {exc.code})")
|
|
return JSONResponse(
|
|
status_code=exc.status_code,
|
|
content=APIResponse.error(
|
|
message=exc.message,
|
|
code=exc.code,
|
|
data=exc.data
|
|
)
|
|
)
|
|
|
|
@app.exception_handler(StarletteHTTPException)
|
|
async def http_exception_handler(request: Request, exc: StarletteHTTPException):
|
|
"""处理标准HTTP异常"""
|
|
logger.error(f"HTTP异常: {exc.detail} (状态码: {exc.status_code})")
|
|
return JSONResponse(
|
|
status_code=exc.status_code,
|
|
content=APIResponse.error(
|
|
message=str(exc.detail),
|
|
code=exc.status_code
|
|
)
|
|
)
|
|
|
|
@app.exception_handler(RequestValidationError)
|
|
async def validation_exception_handler(request: Request, exc: RequestValidationError):
|
|
"""处理请求验证异常"""
|
|
error_details = exc.errors()
|
|
error_messages = []
|
|
|
|
for error in error_details:
|
|
location = " -> ".join(str(loc) for loc in error["loc"])
|
|
message = f"{location}: {error['msg']}"
|
|
error_messages.append(message)
|
|
|
|
error_message = "; ".join(error_messages)
|
|
logger.error(f"验证错误: {error_message}")
|
|
|
|
return JSONResponse(
|
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
content=APIResponse.error(
|
|
message="请求参数验证失败",
|
|
code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
data={"details": error_details}
|
|
)
|
|
)
|
|
|
|
@app.exception_handler(Exception)
|
|
async def general_exception_handler(request: Request, exc: Exception):
|
|
"""处理通用异常"""
|
|
logger.exception(f"未处理的异常: {str(exc)}")
|
|
return JSONResponse(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
content=APIResponse.error(
|
|
message="服务器内部错误",
|
|
code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
data={"detail": str(exc)} if app.debug else None
|
|
)
|
|
) |