aidress/app/exceptions/http_exception.py
2025-03-21 22:49:03 +08:00

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