| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859 |
- from __future__ import annotations
- from typing import Any
- from fastapi import FastAPI, Request
- from fastapi.exceptions import RequestValidationError
- from fastapi.responses import JSONResponse
- from starlette.exceptions import HTTPException as StarletteHTTPException
- class APIError(Exception):
- def __init__(
- self,
- status_code: int,
- code: str,
- message: str,
- detail: Any | None = None,
- ) -> None:
- super().__init__(message)
- self.status_code = status_code
- self.code = code
- self.message = message
- self.detail = detail
- def error_payload(code: str, message: str, detail: Any | None = None) -> dict[str, Any]:
- payload: dict[str, Any] = {"code": code, "message": message}
- if detail is not None:
- payload["detail"] = detail
- return payload
- def install_exception_handlers(app: FastAPI) -> None:
- @app.exception_handler(APIError)
- async def api_error_handler(_: Request, exc: APIError) -> JSONResponse:
- return JSONResponse(
- status_code=exc.status_code,
- content=error_payload(exc.code, exc.message, exc.detail),
- )
- @app.exception_handler(RequestValidationError)
- async def validation_error_handler(
- _: Request, exc: RequestValidationError
- ) -> JSONResponse:
- return JSONResponse(
- status_code=422,
- content=error_payload("validation_error", "请求参数校验失败", exc.errors()),
- )
- @app.exception_handler(StarletteHTTPException)
- async def http_error_handler(_: Request, exc: StarletteHTTPException) -> JSONResponse:
- detail = exc.detail
- if isinstance(detail, dict) and "code" in detail:
- return JSONResponse(status_code=exc.status_code, content=detail)
- return JSONResponse(
- status_code=exc.status_code,
- content=error_payload("http_error", str(detail)),
- )
|