mirror of https://github.com/tiangolo/fastapi.git
Add variants for `custom_request_and_route/tutorial002`
This commit is contained in:
parent
6e902ac8b9
commit
bf8f4068b7
|
|
@ -92,11 +92,11 @@ We can also use this same approach to access the request body in an exception ha
|
|||
|
||||
All we need to do is handle the request inside a `try`/`except` block:
|
||||
|
||||
{* ../../docs_src/custom_request_and_route/tutorial002.py hl[13,15] *}
|
||||
{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[13,15] *}
|
||||
|
||||
If an exception occurs, the`Request` instance will still be in scope, so we can read and make use of the request body when handling the error:
|
||||
|
||||
{* ../../docs_src/custom_request_and_route/tutorial002.py hl[16:18] *}
|
||||
{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[16:18] *}
|
||||
|
||||
## Custom `APIRoute` class in a router { #custom-apiroute-class-in-a-router }
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
from typing import Callable, List
|
||||
|
||||
from fastapi import Body, FastAPI, HTTPException, Request, Response
|
||||
from fastapi.exceptions import RequestValidationError
|
||||
from fastapi.routing import APIRoute
|
||||
|
||||
|
||||
class ValidationErrorLoggingRoute(APIRoute):
|
||||
def get_route_handler(self) -> Callable:
|
||||
original_route_handler = super().get_route_handler()
|
||||
|
||||
async def custom_route_handler(request: Request) -> Response:
|
||||
try:
|
||||
return await original_route_handler(request)
|
||||
except RequestValidationError as exc:
|
||||
body = await request.body()
|
||||
detail = {"errors": exc.errors(), "body": body.decode()}
|
||||
raise HTTPException(status_code=422, detail=detail)
|
||||
|
||||
return custom_route_handler
|
||||
|
||||
|
||||
app = FastAPI()
|
||||
app.router.route_class = ValidationErrorLoggingRoute
|
||||
|
||||
|
||||
@app.post("/")
|
||||
async def sum_numbers(numbers: List[int] = Body()):
|
||||
return sum(numbers)
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
from collections.abc import Callable
|
||||
|
||||
from fastapi import Body, FastAPI, HTTPException, Request, Response
|
||||
from fastapi.exceptions import RequestValidationError
|
||||
from fastapi.routing import APIRoute
|
||||
|
||||
|
||||
class ValidationErrorLoggingRoute(APIRoute):
|
||||
def get_route_handler(self) -> Callable:
|
||||
original_route_handler = super().get_route_handler()
|
||||
|
||||
async def custom_route_handler(request: Request) -> Response:
|
||||
try:
|
||||
return await original_route_handler(request)
|
||||
except RequestValidationError as exc:
|
||||
body = await request.body()
|
||||
detail = {"errors": exc.errors(), "body": body.decode()}
|
||||
raise HTTPException(status_code=422, detail=detail)
|
||||
|
||||
return custom_route_handler
|
||||
|
||||
|
||||
app = FastAPI()
|
||||
app.router.route_class = ValidationErrorLoggingRoute
|
||||
|
||||
|
||||
@app.post("/")
|
||||
async def sum_numbers(numbers: list[int] = Body()):
|
||||
return sum(numbers)
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
from typing import Callable
|
||||
|
||||
from fastapi import Body, FastAPI, HTTPException, Request, Response
|
||||
from fastapi.exceptions import RequestValidationError
|
||||
from fastapi.routing import APIRoute
|
||||
|
||||
|
||||
class ValidationErrorLoggingRoute(APIRoute):
|
||||
def get_route_handler(self) -> Callable:
|
||||
original_route_handler = super().get_route_handler()
|
||||
|
||||
async def custom_route_handler(request: Request) -> Response:
|
||||
try:
|
||||
return await original_route_handler(request)
|
||||
except RequestValidationError as exc:
|
||||
body = await request.body()
|
||||
detail = {"errors": exc.errors(), "body": body.decode()}
|
||||
raise HTTPException(status_code=422, detail=detail)
|
||||
|
||||
return custom_route_handler
|
||||
|
||||
|
||||
app = FastAPI()
|
||||
app.router.route_class = ValidationErrorLoggingRoute
|
||||
|
||||
|
||||
@app.post("/")
|
||||
async def sum_numbers(numbers: list[int] = Body()):
|
||||
return sum(numbers)
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
from collections.abc import Callable
|
||||
|
||||
from fastapi import Body, FastAPI, HTTPException, Request, Response
|
||||
from fastapi.exceptions import RequestValidationError
|
||||
from fastapi.routing import APIRoute
|
||||
|
||||
|
||||
class ValidationErrorLoggingRoute(APIRoute):
|
||||
def get_route_handler(self) -> Callable:
|
||||
original_route_handler = super().get_route_handler()
|
||||
|
||||
async def custom_route_handler(request: Request) -> Response:
|
||||
try:
|
||||
return await original_route_handler(request)
|
||||
except RequestValidationError as exc:
|
||||
body = await request.body()
|
||||
detail = {"errors": exc.errors(), "body": body.decode()}
|
||||
raise HTTPException(status_code=422, detail=detail)
|
||||
|
||||
return custom_route_handler
|
||||
|
||||
|
||||
app = FastAPI()
|
||||
app.router.route_class = ValidationErrorLoggingRoute
|
||||
|
||||
|
||||
@app.post("/")
|
||||
async def sum_numbers(numbers: list[int] = Body()):
|
||||
return sum(numbers)
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
from typing import Callable
|
||||
|
||||
from fastapi import Body, FastAPI, HTTPException, Request, Response
|
||||
from fastapi.exceptions import RequestValidationError
|
||||
from fastapi.routing import APIRoute
|
||||
|
||||
|
||||
class ValidationErrorLoggingRoute(APIRoute):
|
||||
def get_route_handler(self) -> Callable:
|
||||
original_route_handler = super().get_route_handler()
|
||||
|
||||
async def custom_route_handler(request: Request) -> Response:
|
||||
try:
|
||||
return await original_route_handler(request)
|
||||
except RequestValidationError as exc:
|
||||
body = await request.body()
|
||||
detail = {"errors": exc.errors(), "body": body.decode()}
|
||||
raise HTTPException(status_code=422, detail=detail)
|
||||
|
||||
return custom_route_handler
|
||||
|
||||
|
||||
app = FastAPI()
|
||||
app.router.route_class = ValidationErrorLoggingRoute
|
||||
|
||||
|
||||
@app.post("/")
|
||||
async def sum_numbers(numbers: list[int] = Body()):
|
||||
return sum(numbers)
|
||||
|
|
@ -240,6 +240,11 @@ ignore = [
|
|||
"docs_src/path_operation_advanced_configuration/tutorial007_pv1.py" = ["B904"]
|
||||
"docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py" = ["B904"]
|
||||
"docs_src/custom_request_and_route/tutorial002.py" = ["B904"]
|
||||
"docs_src/custom_request_and_route/tutorial002_py39.py" = ["B904"]
|
||||
"docs_src/custom_request_and_route/tutorial002_py310.py" = ["B904"]
|
||||
"docs_src/custom_request_and_route/tutorial002_an.py" = ["B904"]
|
||||
"docs_src/custom_request_and_route/tutorial002_an_py39.py" = ["B904"]
|
||||
"docs_src/custom_request_and_route/tutorial002_an_py310.py" = ["B904"]
|
||||
"docs_src/dependencies/tutorial008_an.py" = ["F821"]
|
||||
"docs_src/dependencies/tutorial008_an_py39.py" = ["F821"]
|
||||
"docs_src/query_params_str_validations/tutorial012_an.py" = ["B006"]
|
||||
|
|
|
|||
|
|
@ -1,17 +1,36 @@
|
|||
import importlib
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict, IsOneOf
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from docs_src.custom_request_and_route.tutorial002 import app
|
||||
|
||||
client = TestClient(app)
|
||||
from tests.utils import needs_py39, needs_py310
|
||||
|
||||
|
||||
def test_endpoint_works():
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial002"),
|
||||
pytest.param("tutorial002_py39", marks=needs_py39),
|
||||
pytest.param("tutorial002_py310", marks=needs_py310),
|
||||
pytest.param("tutorial002_an"),
|
||||
pytest.param("tutorial002_an_py39", marks=needs_py39),
|
||||
pytest.param("tutorial002_an_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.custom_request_and_route.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_endpoint_works(client: TestClient):
|
||||
response = client.post("/", json=[1, 2, 3])
|
||||
assert response.json() == 6
|
||||
|
||||
|
||||
def test_exception_handler_body_access():
|
||||
def test_exception_handler_body_access(client: TestClient):
|
||||
response = client.post("/", json={"numbers": [1, 2, 3]})
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue