from fastapi.encoders import jsonable_encoder from fastapi.exceptions import RequestValidationError, WebSocketRequestValidationError from fastapi.utils import is_body_allowed_for_status_code from fastapi.websockets import WebSocket from starlette.exceptions import HTTPException from starlette.requests import Request from starlette.responses import JSONResponse, Response from starlette.status import WS_1008_POLICY_VIOLATION async def http_exception_handler(request: Request, exc: HTTPException) -> Response: """Default handler for `HTTPException`. Returns a plain `Response` (no body) when the status code disallows a response body (e.g. 204, 304), otherwise returns a JSON response with the exception's `detail` field. """ headers = getattr(exc, "headers", None) if not is_body_allowed_for_status_code(exc.status_code): return Response(status_code=exc.status_code, headers=headers) return JSONResponse( {"detail": exc.detail}, status_code=exc.status_code, headers=headers ) async def request_validation_exception_handler( request: Request, exc: RequestValidationError ) -> JSONResponse: """Default handler for `RequestValidationError`. Returns a 422 JSON response whose body contains the list of validation errors produced by Pydantic. """ return JSONResponse( status_code=422, content={"detail": jsonable_encoder(exc.errors())}, ) async def websocket_request_validation_exception_handler( websocket: WebSocket, exc: WebSocketRequestValidationError ) -> None: """Default handler for `WebSocketRequestValidationError`. Closes the WebSocket connection with policy-violation code 1008 and includes the validation errors in the close reason. """ await websocket.close( code=WS_1008_POLICY_VIOLATION, reason=jsonable_encoder(exc.errors()) )