mirror of https://github.com/tiangolo/fastapi.git
Merge 74fc74564b into 272204c0c7
This commit is contained in:
commit
848902ee4b
|
|
@ -18,10 +18,15 @@ from fastapi import routing
|
||||||
from fastapi.datastructures import Default, DefaultPlaceholder
|
from fastapi.datastructures import Default, DefaultPlaceholder
|
||||||
from fastapi.exception_handlers import (
|
from fastapi.exception_handlers import (
|
||||||
http_exception_handler,
|
http_exception_handler,
|
||||||
|
request_malformed_exception_handler,
|
||||||
request_validation_exception_handler,
|
request_validation_exception_handler,
|
||||||
websocket_request_validation_exception_handler,
|
websocket_request_validation_exception_handler,
|
||||||
)
|
)
|
||||||
from fastapi.exceptions import RequestValidationError, WebSocketRequestValidationError
|
from fastapi.exceptions import (
|
||||||
|
RequestMalformedError,
|
||||||
|
RequestValidationError,
|
||||||
|
WebSocketRequestValidationError,
|
||||||
|
)
|
||||||
from fastapi.logger import logger
|
from fastapi.logger import logger
|
||||||
from fastapi.middleware.asyncexitstack import AsyncExitStackMiddleware
|
from fastapi.middleware.asyncexitstack import AsyncExitStackMiddleware
|
||||||
from fastapi.openapi.docs import (
|
from fastapi.openapi.docs import (
|
||||||
|
|
@ -984,6 +989,9 @@ class FastAPI(Starlette):
|
||||||
Any, Callable[[Request, Any], Union[Response, Awaitable[Response]]]
|
Any, Callable[[Request, Any], Union[Response, Awaitable[Response]]]
|
||||||
] = {} if exception_handlers is None else dict(exception_handlers)
|
] = {} if exception_handlers is None else dict(exception_handlers)
|
||||||
self.exception_handlers.setdefault(HTTPException, http_exception_handler)
|
self.exception_handlers.setdefault(HTTPException, http_exception_handler)
|
||||||
|
self.exception_handlers.setdefault(
|
||||||
|
RequestMalformedError, request_malformed_exception_handler
|
||||||
|
)
|
||||||
self.exception_handlers.setdefault(
|
self.exception_handlers.setdefault(
|
||||||
RequestValidationError, request_validation_exception_handler
|
RequestValidationError, request_validation_exception_handler
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
from fastapi.encoders import jsonable_encoder
|
from fastapi.encoders import jsonable_encoder
|
||||||
from fastapi.exceptions import RequestValidationError, WebSocketRequestValidationError
|
from fastapi.exceptions import (
|
||||||
|
RequestMalformedError,
|
||||||
|
RequestValidationError,
|
||||||
|
WebSocketRequestValidationError,
|
||||||
|
)
|
||||||
from fastapi.utils import is_body_allowed_for_status_code
|
from fastapi.utils import is_body_allowed_for_status_code
|
||||||
from fastapi.websockets import WebSocket
|
from fastapi.websockets import WebSocket
|
||||||
from starlette.exceptions import HTTPException
|
from starlette.exceptions import HTTPException
|
||||||
|
|
@ -17,6 +21,15 @@ async def http_exception_handler(request: Request, exc: HTTPException) -> Respon
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def request_malformed_exception_handler(
|
||||||
|
request: Request, exc: RequestMalformedError
|
||||||
|
) -> JSONResponse:
|
||||||
|
return JSONResponse(
|
||||||
|
status_code=400,
|
||||||
|
content={"detail": jsonable_encoder(exc.errors())},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def request_validation_exception_handler(
|
async def request_validation_exception_handler(
|
||||||
request: Request, exc: RequestValidationError
|
request: Request, exc: RequestValidationError
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
|
|
|
||||||
|
|
@ -199,6 +199,18 @@ class ValidationException(Exception):
|
||||||
return message.rstrip()
|
return message.rstrip()
|
||||||
|
|
||||||
|
|
||||||
|
class RequestMalformedError(ValidationException):
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
errors: Sequence[Any],
|
||||||
|
*,
|
||||||
|
body: Any = None,
|
||||||
|
endpoint_ctx: Optional[EndpointContext] = None,
|
||||||
|
) -> None:
|
||||||
|
super().__init__(errors, endpoint_ctx=endpoint_ctx)
|
||||||
|
self.body = body
|
||||||
|
|
||||||
|
|
||||||
class RequestValidationError(ValidationException):
|
class RequestValidationError(ValidationException):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ from fastapi.encoders import jsonable_encoder
|
||||||
from fastapi.exceptions import (
|
from fastapi.exceptions import (
|
||||||
EndpointContext,
|
EndpointContext,
|
||||||
FastAPIError,
|
FastAPIError,
|
||||||
|
RequestMalformedError,
|
||||||
RequestValidationError,
|
RequestValidationError,
|
||||||
ResponseValidationError,
|
ResponseValidationError,
|
||||||
WebSocketRequestValidationError,
|
WebSocketRequestValidationError,
|
||||||
|
|
@ -388,7 +389,7 @@ def get_request_handler(
|
||||||
else:
|
else:
|
||||||
body = body_bytes
|
body = body_bytes
|
||||||
except json.JSONDecodeError as e:
|
except json.JSONDecodeError as e:
|
||||||
validation_error = RequestValidationError(
|
raise RequestMalformedError(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"type": "json_invalid",
|
"type": "json_invalid",
|
||||||
|
|
@ -400,8 +401,7 @@ def get_request_handler(
|
||||||
],
|
],
|
||||||
body=e.doc,
|
body=e.doc,
|
||||||
endpoint_ctx=endpoint_ctx,
|
endpoint_ctx=endpoint_ctx,
|
||||||
)
|
) from e
|
||||||
raise validation_error from e
|
|
||||||
except HTTPException:
|
except HTTPException:
|
||||||
# If a middleware raises an HTTPException, it should be raised again
|
# If a middleware raises an HTTPException, it should be raised again
|
||||||
raise
|
raise
|
||||||
|
|
|
||||||
|
|
@ -200,7 +200,7 @@ def test_post_broken_body(client: TestClient):
|
||||||
headers={"content-type": "application/json"},
|
headers={"content-type": "application/json"},
|
||||||
content="{some broken json}",
|
content="{some broken json}",
|
||||||
)
|
)
|
||||||
assert response.status_code == 422, response.text
|
assert response.status_code == 400, response.text
|
||||||
assert response.json() == IsDict(
|
assert response.json() == IsDict(
|
||||||
{
|
{
|
||||||
"detail": [
|
"detail": [
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue