from fastapi import FastAPI, HTTPException
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from sqlalchemy.exc import SQLAlchemyError
from starlette.requests import Request
from app.core.business import BusinessError
from app.core.config import settings
from app.core.response import fail
def register_exception_handlers(app: FastAPI) -> None:
@app.exception_handler(BusinessError)
async def business_exception_handler(request: Request, exc: BusinessError):
return JSONResponse(
status_code=200,
content=fail(msg=exc.msg),
)
@app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException):
return JSONResponse(
status_code=exc.status_code,
content=fail(msg=str(exc.detail)),
)
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
return JSONResponse(
status_code=200,
content=fail(msg="参数校验失败", data=exc.errors()),
)
@app.exception_handler(SQLAlchemyError)
async def sqlalchemy_exception_handler(request: Request, exc: SQLAlchemyError):
return JSONResponse(
status_code=500,
content=fail(msg="数据库异常", data=_debug_data(exc)),
)
@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
return JSONResponse(
status_code=500,
content=fail(msg="系统异常", data=_debug_data(exc)),
)
def _debug_data(exc: BaseException) -> dict | None:
if not settings.debug:
return None
return {
"error_type": exc.__class__.__name__,
"error": str(exc),
}