mirror of https://github.com/tiangolo/fastapi.git
add support for starlette's scoped middleware
This commit is contained in:
parent
7c75b55580
commit
71fb6b64c7
|
|
@ -84,6 +84,20 @@ The following arguments are supported:
|
|||
* `minimum_size` - Do not GZip responses that are smaller than this minimum size in bytes. Defaults to `500`.
|
||||
* `compresslevel` - Used during GZip compression. It is an integer ranging from 1 to 9. Defaults to `9`. Lower value results in faster compression but larger file sizes, while higher value results in slower compression but smaller file sizes.
|
||||
|
||||
## Router and Route-Level Middleware Example
|
||||
|
||||
**FastAPI supports adding scoped middleware per route and router. Middleware execution order:**
|
||||
|
||||
- **App‑level middleware** runs on *every* request as soon as it enters your application, before any router or route is matched.
|
||||
- **Router‑level middleware** runs next, wrapping all requests to routes included on that router.
|
||||
- **Route‑level middleware** runs last, just around the specific path operation.
|
||||
|
||||
This gives better control over where and when logic executes.
|
||||
|
||||
The example below shows middleware applied at each scope. Notice how the inner route’s middleware is able to match path params ;)
|
||||
|
||||
{* ../../docs_src/advanced_middleware/tutorial004.py *}
|
||||
|
||||
## Other middlewares
|
||||
|
||||
There are many other ASGI middlewares.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
from fastapi import APIRouter, FastAPI, Request
|
||||
from starlette.middleware import Middleware
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.middleware("http")
|
||||
async def app_middleware(request: Request, call_next):
|
||||
print("App before")
|
||||
response = await call_next(request)
|
||||
print("App after")
|
||||
return response
|
||||
|
||||
|
||||
async def outer_middleware(request: Request, call_next):
|
||||
print("Outer before")
|
||||
response = await call_next(request)
|
||||
print("Outer after")
|
||||
return response
|
||||
|
||||
|
||||
outer = APIRouter(
|
||||
prefix="/outer",
|
||||
middleware=[Middleware(BaseHTTPMiddleware, dispatch=outer_middleware)],
|
||||
)
|
||||
|
||||
|
||||
async def name_middleware(request: Request, call_next):
|
||||
print(f"Hi {request.path_params.get('name')}!")
|
||||
response = await call_next(request)
|
||||
print(f"Bye {request.path_params.get('name')}!")
|
||||
return response
|
||||
|
||||
|
||||
inner = APIRouter(prefix="/inner")
|
||||
|
||||
|
||||
@inner.get(
|
||||
"/{name}",
|
||||
middleware=[Middleware(BaseHTTPMiddleware, dispatch=name_middleware)],
|
||||
)
|
||||
async def hello(name: str):
|
||||
print("Handler")
|
||||
return {"message": f"Hello {name} from inner!"}
|
||||
|
||||
|
||||
@outer.get("/")
|
||||
async def outer_hello():
|
||||
print("Handler")
|
||||
return {"message": "Hello from outer!"}
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def app_hello():
|
||||
print("Handler")
|
||||
return {"message": "Hello from app!"}
|
||||
|
||||
|
||||
outer.include_router(inner)
|
||||
app.include_router(outer)
|
||||
|
|
@ -1084,6 +1084,7 @@ class FastAPI(Starlette):
|
|||
generate_unique_id_function: Callable[[routing.APIRoute], str] = Default(
|
||||
generate_unique_id
|
||||
),
|
||||
middleware: Optional[List[Middleware]] = None,
|
||||
) -> None:
|
||||
self.router.add_api_route(
|
||||
path,
|
||||
|
|
@ -1110,6 +1111,7 @@ class FastAPI(Starlette):
|
|||
name=name,
|
||||
openapi_extra=openapi_extra,
|
||||
generate_unique_id_function=generate_unique_id_function,
|
||||
middleware=middleware,
|
||||
)
|
||||
|
||||
def api_route(
|
||||
|
|
@ -1140,6 +1142,7 @@ class FastAPI(Starlette):
|
|||
generate_unique_id_function: Callable[[routing.APIRoute], str] = Default(
|
||||
generate_unique_id
|
||||
),
|
||||
middleware: Optional[List[Middleware]] = None,
|
||||
) -> Callable[[DecoratedCallable], DecoratedCallable]:
|
||||
def decorator(func: DecoratedCallable) -> DecoratedCallable:
|
||||
self.router.add_api_route(
|
||||
|
|
@ -1167,6 +1170,7 @@ class FastAPI(Starlette):
|
|||
name=name,
|
||||
openapi_extra=openapi_extra,
|
||||
generate_unique_id_function=generate_unique_id_function,
|
||||
middleware=middleware,
|
||||
)
|
||||
return func
|
||||
|
||||
|
|
@ -1788,6 +1792,21 @@ class FastAPI(Starlette):
|
|||
"""
|
||||
),
|
||||
] = Default(generate_unique_id),
|
||||
middleware: Annotated[
|
||||
Optional[Sequence[Middleware]],
|
||||
Doc(
|
||||
"""
|
||||
List of middleware to apply to all requests handled by this route.
|
||||
|
||||
Route-level middleware is executed after application-level and router-level middleware.
|
||||
Any middleware declared on the router will be called before this route's middleware.
|
||||
Middleware are applied in reverse order: the last middleware in this list is the first to be called.
|
||||
|
||||
Read more about it in the
|
||||
[FastAPI docs for Middleware](https://fastapi.tiangolo.com/advanced/middleware/)
|
||||
"""
|
||||
),
|
||||
] = None,
|
||||
) -> Callable[[DecoratedCallable], DecoratedCallable]:
|
||||
"""
|
||||
Add a *path operation* using an HTTP GET operation.
|
||||
|
|
@ -1828,6 +1847,7 @@ class FastAPI(Starlette):
|
|||
callbacks=callbacks,
|
||||
openapi_extra=openapi_extra,
|
||||
generate_unique_id_function=generate_unique_id_function,
|
||||
middleware=middleware,
|
||||
)
|
||||
|
||||
def put(
|
||||
|
|
@ -2161,6 +2181,21 @@ class FastAPI(Starlette):
|
|||
"""
|
||||
),
|
||||
] = Default(generate_unique_id),
|
||||
middleware: Annotated[
|
||||
Optional[Sequence[Middleware]],
|
||||
Doc(
|
||||
"""
|
||||
List of middleware to apply to all requests handled by this route.
|
||||
|
||||
Route-level middleware is executed after application-level and router-level middleware.
|
||||
Any middleware declared on the router will be called before this route's middleware.
|
||||
Middleware are applied in reverse order: the last middleware in this list is the first to be called.
|
||||
|
||||
Read more about it in the
|
||||
[FastAPI docs for Middleware](https://fastapi.tiangolo.com/advanced/middleware/)
|
||||
"""
|
||||
),
|
||||
] = None,
|
||||
) -> Callable[[DecoratedCallable], DecoratedCallable]:
|
||||
"""
|
||||
Add a *path operation* using an HTTP PUT operation.
|
||||
|
|
@ -2206,6 +2241,7 @@ class FastAPI(Starlette):
|
|||
callbacks=callbacks,
|
||||
openapi_extra=openapi_extra,
|
||||
generate_unique_id_function=generate_unique_id_function,
|
||||
middleware=middleware,
|
||||
)
|
||||
|
||||
def post(
|
||||
|
|
@ -2539,6 +2575,21 @@ class FastAPI(Starlette):
|
|||
"""
|
||||
),
|
||||
] = Default(generate_unique_id),
|
||||
middleware: Annotated[
|
||||
Optional[Sequence[Middleware]],
|
||||
Doc(
|
||||
"""
|
||||
List of middleware to apply to all requests handled by this route.
|
||||
|
||||
Route-level middleware is executed after application-level and router-level middleware.
|
||||
Any middleware declared on the router will be called before this route's middleware.
|
||||
Middleware are applied in reverse order: the last middleware in this list is the first to be called.
|
||||
|
||||
Read more about it in the
|
||||
[FastAPI docs for Middleware](https://fastapi.tiangolo.com/advanced/middleware/)
|
||||
"""
|
||||
),
|
||||
] = None,
|
||||
) -> Callable[[DecoratedCallable], DecoratedCallable]:
|
||||
"""
|
||||
Add a *path operation* using an HTTP POST operation.
|
||||
|
|
@ -2584,6 +2635,7 @@ class FastAPI(Starlette):
|
|||
callbacks=callbacks,
|
||||
openapi_extra=openapi_extra,
|
||||
generate_unique_id_function=generate_unique_id_function,
|
||||
middleware=middleware,
|
||||
)
|
||||
|
||||
def delete(
|
||||
|
|
@ -2917,6 +2969,21 @@ class FastAPI(Starlette):
|
|||
"""
|
||||
),
|
||||
] = Default(generate_unique_id),
|
||||
middleware: Annotated[
|
||||
Optional[Sequence[Middleware]],
|
||||
Doc(
|
||||
"""
|
||||
List of middleware to apply to all requests handled by this route.
|
||||
|
||||
Route-level middleware is executed after application-level and router-level middleware.
|
||||
Any middleware declared on the router will be called before this route's middleware.
|
||||
Middleware are applied in reverse order: the last middleware in this list is the first to be called.
|
||||
|
||||
Read more about it in the
|
||||
[FastAPI docs for Middleware](https://fastapi.tiangolo.com/advanced/middleware/)
|
||||
"""
|
||||
),
|
||||
] = None,
|
||||
) -> Callable[[DecoratedCallable], DecoratedCallable]:
|
||||
"""
|
||||
Add a *path operation* using an HTTP DELETE operation.
|
||||
|
|
@ -2957,6 +3024,7 @@ class FastAPI(Starlette):
|
|||
callbacks=callbacks,
|
||||
openapi_extra=openapi_extra,
|
||||
generate_unique_id_function=generate_unique_id_function,
|
||||
middleware=middleware,
|
||||
)
|
||||
|
||||
def options(
|
||||
|
|
@ -3290,6 +3358,21 @@ class FastAPI(Starlette):
|
|||
"""
|
||||
),
|
||||
] = Default(generate_unique_id),
|
||||
middleware: Annotated[
|
||||
Optional[Sequence[Middleware]],
|
||||
Doc(
|
||||
"""
|
||||
List of middleware to apply to all requests handled by this route.
|
||||
|
||||
Route-level middleware is executed after application-level and router-level middleware.
|
||||
Any middleware declared on the router will be called before this route's middleware.
|
||||
Middleware are applied in reverse order: the last middleware in this list is the first to be called.
|
||||
|
||||
Read more about it in the
|
||||
[FastAPI docs for Middleware](https://fastapi.tiangolo.com/advanced/middleware/)
|
||||
"""
|
||||
),
|
||||
] = None,
|
||||
) -> Callable[[DecoratedCallable], DecoratedCallable]:
|
||||
"""
|
||||
Add a *path operation* using an HTTP OPTIONS operation.
|
||||
|
|
@ -3330,6 +3413,7 @@ class FastAPI(Starlette):
|
|||
callbacks=callbacks,
|
||||
openapi_extra=openapi_extra,
|
||||
generate_unique_id_function=generate_unique_id_function,
|
||||
middleware=middleware,
|
||||
)
|
||||
|
||||
def head(
|
||||
|
|
@ -3663,6 +3747,21 @@ class FastAPI(Starlette):
|
|||
"""
|
||||
),
|
||||
] = Default(generate_unique_id),
|
||||
middleware: Annotated[
|
||||
Optional[Sequence[Middleware]],
|
||||
Doc(
|
||||
"""
|
||||
List of middleware to apply to all requests handled by this route.
|
||||
|
||||
Route-level middleware is executed after application-level and router-level middleware.
|
||||
Any middleware declared on the router will be called before this route's middleware.
|
||||
Middleware are applied in reverse order: the last middleware in this list is the first to be called.
|
||||
|
||||
Read more about it in the
|
||||
[FastAPI docs for Middleware](https://fastapi.tiangolo.com/advanced/middleware/)
|
||||
"""
|
||||
),
|
||||
] = None,
|
||||
) -> Callable[[DecoratedCallable], DecoratedCallable]:
|
||||
"""
|
||||
Add a *path operation* using an HTTP HEAD operation.
|
||||
|
|
@ -3703,6 +3802,7 @@ class FastAPI(Starlette):
|
|||
callbacks=callbacks,
|
||||
openapi_extra=openapi_extra,
|
||||
generate_unique_id_function=generate_unique_id_function,
|
||||
middleware=middleware,
|
||||
)
|
||||
|
||||
def patch(
|
||||
|
|
@ -4036,6 +4136,21 @@ class FastAPI(Starlette):
|
|||
"""
|
||||
),
|
||||
] = Default(generate_unique_id),
|
||||
middleware: Annotated[
|
||||
Optional[Sequence[Middleware]],
|
||||
Doc(
|
||||
"""
|
||||
List of middleware to apply to all requests handled by this route.
|
||||
|
||||
Route-level middleware is executed after application-level and router-level middleware.
|
||||
Any middleware declared on the router will be called before this route's middleware.
|
||||
Middleware are applied in reverse order: the last middleware in this list is the first to be called.
|
||||
|
||||
Read more about it in the
|
||||
[FastAPI docs for Middleware](https://fastapi.tiangolo.com/advanced/middleware/)
|
||||
"""
|
||||
),
|
||||
] = None,
|
||||
) -> Callable[[DecoratedCallable], DecoratedCallable]:
|
||||
"""
|
||||
Add a *path operation* using an HTTP PATCH operation.
|
||||
|
|
@ -4081,6 +4196,7 @@ class FastAPI(Starlette):
|
|||
callbacks=callbacks,
|
||||
openapi_extra=openapi_extra,
|
||||
generate_unique_id_function=generate_unique_id_function,
|
||||
middleware=middleware,
|
||||
)
|
||||
|
||||
def trace(
|
||||
|
|
@ -4414,6 +4530,21 @@ class FastAPI(Starlette):
|
|||
"""
|
||||
),
|
||||
] = Default(generate_unique_id),
|
||||
middleware: Annotated[
|
||||
Optional[Sequence[Middleware]],
|
||||
Doc(
|
||||
"""
|
||||
List of middleware to apply to all requests handled by this route.
|
||||
|
||||
Route-level middleware is executed after application-level and router-level middleware.
|
||||
Any middleware declared on the router will be called before this route's middleware.
|
||||
Middleware are applied in reverse order: the last middleware in this list is the first to be called.
|
||||
|
||||
Read more about it in the
|
||||
[FastAPI docs for Middleware](https://fastapi.tiangolo.com/advanced/middleware/)
|
||||
"""
|
||||
),
|
||||
] = None,
|
||||
) -> Callable[[DecoratedCallable], DecoratedCallable]:
|
||||
"""
|
||||
Add a *path operation* using an HTTP TRACE operation.
|
||||
|
|
@ -4454,6 +4585,7 @@ class FastAPI(Starlette):
|
|||
callbacks=callbacks,
|
||||
openapi_extra=openapi_extra,
|
||||
generate_unique_id_function=generate_unique_id_function,
|
||||
middleware=middleware,
|
||||
)
|
||||
|
||||
def websocket_route(
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ from pydantic import BaseModel
|
|||
from starlette import routing
|
||||
from starlette.concurrency import run_in_threadpool
|
||||
from starlette.exceptions import HTTPException
|
||||
from starlette.middleware import Middleware
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import JSONResponse, Response
|
||||
from starlette.routing import (
|
||||
|
|
@ -459,6 +460,7 @@ class APIRoute(routing.Route):
|
|||
generate_unique_id_function: Union[
|
||||
Callable[["APIRoute"], str], DefaultPlaceholder
|
||||
] = Default(generate_unique_id),
|
||||
middleware: Optional[Sequence[Middleware]] = None,
|
||||
) -> None:
|
||||
self.path = path
|
||||
self.endpoint = endpoint
|
||||
|
|
@ -566,8 +568,13 @@ class APIRoute(routing.Route):
|
|||
name=self.unique_id,
|
||||
embed_body_fields=self._embed_body_fields,
|
||||
)
|
||||
self.middleware = middleware
|
||||
self.app = request_response(self.get_route_handler())
|
||||
|
||||
if middleware is not None:
|
||||
for cls, args, kwargs in reversed(middleware):
|
||||
self.app = cls(self.app, *args, **kwargs)
|
||||
|
||||
def get_route_handler(self) -> Callable[[Request], Coroutine[Any, Any, Response]]:
|
||||
return get_request_handler(
|
||||
dependant=self.dependant,
|
||||
|
|
@ -833,6 +840,21 @@ class APIRouter(routing.Router):
|
|||
"""
|
||||
),
|
||||
] = Default(generate_unique_id),
|
||||
middleware: Annotated[
|
||||
Optional[Sequence[Middleware]],
|
||||
Doc(
|
||||
"""
|
||||
List of middleware to apply to all requests handled by this router.
|
||||
|
||||
Router-level middleware is executed after application-level middleware.
|
||||
When multiple routers declare middleware, the outermost (furthest) router's middleware runs first.
|
||||
Middleware are applied in reverse order: the last middleware in this list is the first to be called.
|
||||
|
||||
Read more about it in the
|
||||
[FastAPI docs for Middleware](https://fastapi.tiangolo.com/advanced/middleware/)
|
||||
"""
|
||||
),
|
||||
] = None,
|
||||
) -> None:
|
||||
super().__init__(
|
||||
routes=routes,
|
||||
|
|
@ -841,6 +863,7 @@ class APIRouter(routing.Router):
|
|||
on_startup=on_startup,
|
||||
on_shutdown=on_shutdown,
|
||||
lifespan=lifespan,
|
||||
middleware=middleware,
|
||||
)
|
||||
if prefix:
|
||||
assert prefix.startswith("/"), "A path prefix must start with '/'"
|
||||
|
|
@ -858,6 +881,7 @@ class APIRouter(routing.Router):
|
|||
self.route_class = route_class
|
||||
self.default_response_class = default_response_class
|
||||
self.generate_unique_id_function = generate_unique_id_function
|
||||
self.middleware = middleware
|
||||
|
||||
def route(
|
||||
self,
|
||||
|
|
@ -911,6 +935,7 @@ class APIRouter(routing.Router):
|
|||
generate_unique_id_function: Union[
|
||||
Callable[[APIRoute], str], DefaultPlaceholder
|
||||
] = Default(generate_unique_id),
|
||||
middleware: Optional[List[Middleware]] = None,
|
||||
) -> None:
|
||||
route_class = route_class_override or self.route_class
|
||||
responses = responses or {}
|
||||
|
|
@ -930,6 +955,9 @@ class APIRouter(routing.Router):
|
|||
current_generate_unique_id = get_value_or_default(
|
||||
generate_unique_id_function, self.generate_unique_id_function
|
||||
)
|
||||
if middleware and self.middleware:
|
||||
middleware = self.middleware + middleware
|
||||
|
||||
route = route_class(
|
||||
self.prefix + path,
|
||||
endpoint=endpoint,
|
||||
|
|
@ -957,6 +985,7 @@ class APIRouter(routing.Router):
|
|||
callbacks=current_callbacks,
|
||||
openapi_extra=openapi_extra,
|
||||
generate_unique_id_function=current_generate_unique_id,
|
||||
middleware=middleware or self.middleware,
|
||||
)
|
||||
self.routes.append(route)
|
||||
|
||||
|
|
@ -989,6 +1018,7 @@ class APIRouter(routing.Router):
|
|||
generate_unique_id_function: Callable[[APIRoute], str] = Default(
|
||||
generate_unique_id
|
||||
),
|
||||
middleware: Optional[List[Middleware]] = None,
|
||||
) -> Callable[[DecoratedCallable], DecoratedCallable]:
|
||||
def decorator(func: DecoratedCallable) -> DecoratedCallable:
|
||||
self.add_api_route(
|
||||
|
|
@ -1017,6 +1047,7 @@ class APIRouter(routing.Router):
|
|||
callbacks=callbacks,
|
||||
openapi_extra=openapi_extra,
|
||||
generate_unique_id_function=generate_unique_id_function,
|
||||
middleware=middleware,
|
||||
)
|
||||
return func
|
||||
|
||||
|
|
@ -1328,6 +1359,7 @@ class APIRouter(routing.Router):
|
|||
callbacks=current_callbacks,
|
||||
openapi_extra=route.openapi_extra,
|
||||
generate_unique_id_function=current_generate_unique_id,
|
||||
middleware=route.middleware,
|
||||
)
|
||||
elif isinstance(route, routing.Route):
|
||||
methods = list(route.methods or [])
|
||||
|
|
@ -1694,6 +1726,21 @@ class APIRouter(routing.Router):
|
|||
"""
|
||||
),
|
||||
] = Default(generate_unique_id),
|
||||
middleware: Annotated[
|
||||
Optional[Sequence[Middleware]],
|
||||
Doc(
|
||||
"""
|
||||
List of middleware to apply to all requests handled by this route.
|
||||
|
||||
Route-level middleware is executed after application-level and router-level middleware.
|
||||
Any middleware declared on the router will be called before this route's middleware.
|
||||
Middleware are applied in reverse order: the last middleware in this list is the first to be called.
|
||||
|
||||
Read more about it in the
|
||||
[FastAPI docs for Middleware](https://fastapi.tiangolo.com/advanced/middleware/)
|
||||
"""
|
||||
),
|
||||
] = None,
|
||||
) -> Callable[[DecoratedCallable], DecoratedCallable]:
|
||||
"""
|
||||
Add a *path operation* using an HTTP GET operation.
|
||||
|
|
@ -1738,6 +1785,7 @@ class APIRouter(routing.Router):
|
|||
callbacks=callbacks,
|
||||
openapi_extra=openapi_extra,
|
||||
generate_unique_id_function=generate_unique_id_function,
|
||||
middleware=middleware,
|
||||
)
|
||||
|
||||
def put(
|
||||
|
|
@ -2071,6 +2119,21 @@ class APIRouter(routing.Router):
|
|||
"""
|
||||
),
|
||||
] = Default(generate_unique_id),
|
||||
middleware: Annotated[
|
||||
Optional[Sequence[Middleware]],
|
||||
Doc(
|
||||
"""
|
||||
List of middleware to apply to all requests handled by this route.
|
||||
|
||||
Route-level middleware is executed after application-level and router-level middleware.
|
||||
Any middleware declared on the router will be called before this route's middleware.
|
||||
Middleware are applied in reverse order: the last middleware in this list is the first to be called.
|
||||
|
||||
Read more about it in the
|
||||
[FastAPI docs for Middleware](https://fastapi.tiangolo.com/advanced/middleware/)
|
||||
"""
|
||||
),
|
||||
] = None,
|
||||
) -> Callable[[DecoratedCallable], DecoratedCallable]:
|
||||
"""
|
||||
Add a *path operation* using an HTTP PUT operation.
|
||||
|
|
@ -2120,6 +2183,7 @@ class APIRouter(routing.Router):
|
|||
callbacks=callbacks,
|
||||
openapi_extra=openapi_extra,
|
||||
generate_unique_id_function=generate_unique_id_function,
|
||||
middleware=middleware,
|
||||
)
|
||||
|
||||
def post(
|
||||
|
|
@ -2453,6 +2517,21 @@ class APIRouter(routing.Router):
|
|||
"""
|
||||
),
|
||||
] = Default(generate_unique_id),
|
||||
middleware: Annotated[
|
||||
Optional[Sequence[Middleware]],
|
||||
Doc(
|
||||
"""
|
||||
List of middleware to apply to all requests handled by this route.
|
||||
|
||||
Route-level middleware is executed after application-level and router-level middleware.
|
||||
Any middleware declared on the router will be called before this route's middleware.
|
||||
Middleware are applied in reverse order: the last middleware in this list is the first to be called.
|
||||
|
||||
Read more about it in the
|
||||
[FastAPI docs for Middleware](https://fastapi.tiangolo.com/advanced/middleware/)
|
||||
"""
|
||||
),
|
||||
] = None,
|
||||
) -> Callable[[DecoratedCallable], DecoratedCallable]:
|
||||
"""
|
||||
Add a *path operation* using an HTTP POST operation.
|
||||
|
|
@ -2502,6 +2581,7 @@ class APIRouter(routing.Router):
|
|||
callbacks=callbacks,
|
||||
openapi_extra=openapi_extra,
|
||||
generate_unique_id_function=generate_unique_id_function,
|
||||
middleware=middleware,
|
||||
)
|
||||
|
||||
def delete(
|
||||
|
|
@ -2835,6 +2915,21 @@ class APIRouter(routing.Router):
|
|||
"""
|
||||
),
|
||||
] = Default(generate_unique_id),
|
||||
middleware: Annotated[
|
||||
Optional[Sequence[Middleware]],
|
||||
Doc(
|
||||
"""
|
||||
List of middleware to apply to all requests handled by this route.
|
||||
|
||||
Route-level middleware is executed after application-level and router-level middleware.
|
||||
Any middleware declared on the router will be called before this route's middleware.
|
||||
Middleware are applied in reverse order: the last middleware in this list is the first to be called.
|
||||
|
||||
Read more about it in the
|
||||
[FastAPI docs for Middleware](https://fastapi.tiangolo.com/advanced/middleware/)
|
||||
"""
|
||||
),
|
||||
] = None,
|
||||
) -> Callable[[DecoratedCallable], DecoratedCallable]:
|
||||
"""
|
||||
Add a *path operation* using an HTTP DELETE operation.
|
||||
|
|
@ -2879,6 +2974,7 @@ class APIRouter(routing.Router):
|
|||
callbacks=callbacks,
|
||||
openapi_extra=openapi_extra,
|
||||
generate_unique_id_function=generate_unique_id_function,
|
||||
middleware=middleware,
|
||||
)
|
||||
|
||||
def options(
|
||||
|
|
@ -3212,6 +3308,21 @@ class APIRouter(routing.Router):
|
|||
"""
|
||||
),
|
||||
] = Default(generate_unique_id),
|
||||
middleware: Annotated[
|
||||
Optional[Sequence[Middleware]],
|
||||
Doc(
|
||||
"""
|
||||
List of middleware to apply to all requests handled by this route.
|
||||
|
||||
Route-level middleware is executed after application-level and router-level middleware.
|
||||
Any middleware declared on the router will be called before this route's middleware.
|
||||
Middleware are applied in reverse order: the last middleware in this list is the first to be called.
|
||||
|
||||
Read more about it in the
|
||||
[FastAPI docs for Middleware](https://fastapi.tiangolo.com/advanced/middleware/)
|
||||
"""
|
||||
),
|
||||
] = None,
|
||||
) -> Callable[[DecoratedCallable], DecoratedCallable]:
|
||||
"""
|
||||
Add a *path operation* using an HTTP OPTIONS operation.
|
||||
|
|
@ -3256,6 +3367,7 @@ class APIRouter(routing.Router):
|
|||
callbacks=callbacks,
|
||||
openapi_extra=openapi_extra,
|
||||
generate_unique_id_function=generate_unique_id_function,
|
||||
middleware=middleware,
|
||||
)
|
||||
|
||||
def head(
|
||||
|
|
@ -3589,6 +3701,21 @@ class APIRouter(routing.Router):
|
|||
"""
|
||||
),
|
||||
] = Default(generate_unique_id),
|
||||
middleware: Annotated[
|
||||
Optional[Sequence[Middleware]],
|
||||
Doc(
|
||||
"""
|
||||
List of middleware to apply to all requests handled by this route.
|
||||
|
||||
Route-level middleware is executed after application-level and router-level middleware.
|
||||
Any middleware declared on the router will be called before this route's middleware.
|
||||
Middleware are applied in reverse order: the last middleware in this list is the first to be called.
|
||||
|
||||
Read more about it in the
|
||||
[FastAPI docs for Middleware](https://fastapi.tiangolo.com/advanced/middleware/)
|
||||
"""
|
||||
),
|
||||
] = None,
|
||||
) -> Callable[[DecoratedCallable], DecoratedCallable]:
|
||||
"""
|
||||
Add a *path operation* using an HTTP HEAD operation.
|
||||
|
|
@ -3638,6 +3765,7 @@ class APIRouter(routing.Router):
|
|||
callbacks=callbacks,
|
||||
openapi_extra=openapi_extra,
|
||||
generate_unique_id_function=generate_unique_id_function,
|
||||
middleware=middleware,
|
||||
)
|
||||
|
||||
def patch(
|
||||
|
|
@ -3971,6 +4099,21 @@ class APIRouter(routing.Router):
|
|||
"""
|
||||
),
|
||||
] = Default(generate_unique_id),
|
||||
middleware: Annotated[
|
||||
Optional[Sequence[Middleware]],
|
||||
Doc(
|
||||
"""
|
||||
List of middleware to apply to all requests handled by this route.
|
||||
|
||||
Route-level middleware is executed after application-level and router-level middleware.
|
||||
Any middleware declared on the router will be called before this route's middleware.
|
||||
Middleware are applied in reverse order: the last middleware in this list is the first to be called.
|
||||
|
||||
Read more about it in the
|
||||
[FastAPI docs for Middleware](https://fastapi.tiangolo.com/advanced/middleware/)
|
||||
"""
|
||||
),
|
||||
] = None,
|
||||
) -> Callable[[DecoratedCallable], DecoratedCallable]:
|
||||
"""
|
||||
Add a *path operation* using an HTTP PATCH operation.
|
||||
|
|
@ -4020,6 +4163,7 @@ class APIRouter(routing.Router):
|
|||
callbacks=callbacks,
|
||||
openapi_extra=openapi_extra,
|
||||
generate_unique_id_function=generate_unique_id_function,
|
||||
middleware=middleware,
|
||||
)
|
||||
|
||||
def trace(
|
||||
|
|
@ -4353,6 +4497,21 @@ class APIRouter(routing.Router):
|
|||
"""
|
||||
),
|
||||
] = Default(generate_unique_id),
|
||||
middleware: Annotated[
|
||||
Optional[Sequence[Middleware]],
|
||||
Doc(
|
||||
"""
|
||||
List of middleware to apply to all requests handled by this route.
|
||||
|
||||
Route-level middleware is executed after application-level and router-level middleware.
|
||||
Any middleware declared on the router will be called before this route's middleware.
|
||||
Middleware are applied in reverse order: the last middleware in this list is the first to be called.
|
||||
|
||||
Read more about it in the
|
||||
[FastAPI docs for Middleware](https://fastapi.tiangolo.com/advanced/middleware/)
|
||||
"""
|
||||
),
|
||||
] = None,
|
||||
) -> Callable[[DecoratedCallable], DecoratedCallable]:
|
||||
"""
|
||||
Add a *path operation* using an HTTP TRACE operation.
|
||||
|
|
@ -4402,6 +4561,7 @@ class APIRouter(routing.Router):
|
|||
callbacks=callbacks,
|
||||
openapi_extra=openapi_extra,
|
||||
generate_unique_id_function=generate_unique_id_function,
|
||||
middleware=middleware,
|
||||
)
|
||||
|
||||
@deprecated(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
from fastapi.testclient import TestClient
|
||||
|
||||
from docs_src.advanced_middleware.tutorial004 import app
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
|
||||
def test_app_middleware_called_once(capsys):
|
||||
r = client.get("/")
|
||||
assert r.status_code == 200
|
||||
|
||||
captured = capsys.readouterr().out
|
||||
assert captured.count("App before") == 1
|
||||
assert captured.count("Outer before") == 0
|
||||
assert captured.count("Handler") == 1
|
||||
assert captured.count("Outer after") == 0
|
||||
assert captured.count("App after") == 1
|
||||
|
||||
|
||||
def test_outer_middleware_called_once(capsys):
|
||||
r = client.get("/outer/")
|
||||
assert r.status_code == 200
|
||||
|
||||
captured = capsys.readouterr().out
|
||||
assert captured.count("App before") == 1
|
||||
assert captured.count("Outer before") == 1
|
||||
assert captured.count("Handler") == 1
|
||||
assert captured.count("Outer after") == 1
|
||||
assert captured.count("App after") == 1
|
||||
|
||||
|
||||
def test_name_middleware_called_once(capsys):
|
||||
name = "you"
|
||||
r = client.get(f"/outer/inner/{name}")
|
||||
assert r.status_code == 200
|
||||
assert r.json() == {"message": f"Hello {name} from inner!"}
|
||||
|
||||
captured = capsys.readouterr().out
|
||||
seq = [
|
||||
"App before",
|
||||
"Outer before",
|
||||
f"Hi {name}!",
|
||||
"Handler",
|
||||
f"Bye {name}!",
|
||||
"Outer after",
|
||||
"App after",
|
||||
]
|
||||
for msg in seq:
|
||||
assert captured.count(msg) == 1
|
||||
|
||||
idx = 0
|
||||
for msg in seq:
|
||||
next_idx = captured.find(msg, idx)
|
||||
assert next_idx >= idx
|
||||
idx = next_idx
|
||||
Loading…
Reference in New Issue