from typing import Any from fastapi import FastAPI, HTTPException, Request, status from fastapi.encoders import jsonable_encoder from fastapi.exceptions import RequestValidationError from fastapi.responses import JSONResponse from starlette.exceptions import HTTPException as StarletteHTTPException from src.utils.helpers import first def register_exception_handler(app: FastAPI): @app.exception_handler(RequestValidationError) async def validation_exception_handler(request: Request, exc: RequestValidationError): """请求参数验证错误处理""" error = first(exc.errors()) field = error.get('loc')[1] or '' return JSONResponse( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, content=jsonable_encoder({ "status_code": status.HTTP_422_UNPROCESSABLE_ENTITY, "message": "{} param {}".format(field, error.get('msg')), "detail": exc.errors()}), ) @app.exception_handler(StarletteHTTPException) async def http_exception_handler(request: Request, exc: StarletteHTTPException): """Http 异常处理""" return JSONResponse( status_code=exc.status_code, content=jsonable_encoder({ "status_code": exc.status_code, "message": exc.detail}), ) @app.exception_handler(Exception) async def exception_callback(request: Request, exc: Exception): """其他异常处理,遇到其他问题再自定义异常""" return JSONResponse( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, content=jsonable_encoder({ "status_code": status.HTTP_500_INTERNAL_SERVER_ERROR, "message": "Internal Server Error", # "detail": ''.join(exc.args) }), ) class CommonHttpException(HTTPException): def __init__(self, detail, status_code, **kwargs: dict[str, Any]) -> None: super().__init__(status_code=status_code, detail=detail, **kwargs) class DetailedHTTPException(HTTPException): STATUS_CODE = status.HTTP_500_INTERNAL_SERVER_ERROR DETAIL = "Server error" def __init__(self, **kwargs: dict[str, Any]) -> None: super().__init__(status_code=self.STATUS_CODE, detail=self.DETAIL, **kwargs) class PermissionDenied(DetailedHTTPException): STATUS_CODE = status.HTTP_403_FORBIDDEN DETAIL = "Permission denied" class NotFound(DetailedHTTPException): STATUS_CODE = status.HTTP_404_NOT_FOUND class BadRequest(DetailedHTTPException): STATUS_CODE = status.HTTP_400_BAD_REQUEST DETAIL = "Bad Request" class UnprocessableEntity(DetailedHTTPException): STATUS_CODE = status.HTTP_422_UNPROCESSABLE_ENTITY DETAIL = "Unprocessable entity" class NotAuthenticated(DetailedHTTPException): STATUS_CODE = status.HTTP_401_UNAUTHORIZED DETAIL = "User not authenticated" class WxResponseError(DetailedHTTPException): STATUS_CODE = status.HTTP_400_BAD_REQUEST DETAIL = "请求微信异常" def __init__(self) -> None: super().__init__(headers={"WWW-Authenticate": "Bearer"})