-
-
Notifications
You must be signed in to change notification settings - Fork 402
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(core): new base middleware (#3996)
- Loading branch information
1 parent
27a5b1d
commit 6054667
Showing
11 changed files
with
489 additions
and
13 deletions.
There are no files selected for viewing
17 changes: 17 additions & 0 deletions
17
docs/examples/middleware/abstract_middleware_migration_new.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import anyio | ||
|
||
from litestar import Litestar | ||
from litestar.middleware import ASGIMiddleware | ||
from litestar.types import ASGIApp, Receive, Scope, Send | ||
|
||
|
||
class TimeoutMiddleware(ASGIMiddleware): | ||
def __init__(self, timeout: float): | ||
self.timeout = timeout | ||
|
||
async def handle(self, scope: Scope, receive: Receive, send: Send, next_app: ASGIApp) -> None: | ||
with anyio.move_on_after(self.timeout): | ||
await next_app(scope, receive, send) | ||
|
||
|
||
app = Litestar(middleware=[TimeoutMiddleware(timeout=5)]) |
32 changes: 32 additions & 0 deletions
32
docs/examples/middleware/abstract_middleware_migration_old.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import anyio | ||
|
||
from litestar import Litestar | ||
from litestar.middleware import AbstractMiddleware, DefineMiddleware | ||
from litestar.types import ASGIApp, Receive, Scope, Scopes, Send | ||
|
||
|
||
class TimeoutMiddleware(AbstractMiddleware): | ||
def __init__( | ||
self, | ||
app: ASGIApp, | ||
timeout: float, | ||
exclude: str | list[str] | None = None, | ||
exclude_opt_key: str | None = None, | ||
scopes: Scopes | None = None, | ||
): | ||
self.timeout = timeout | ||
super().__init__(app=app, exclude=exclude, exclude_opt_key=exclude_opt_key, scopes=scopes) | ||
|
||
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: | ||
with anyio.move_on_after(self.timeout): | ||
await self.app(scope, receive, send) | ||
|
||
|
||
app = Litestar( | ||
middleware=[ | ||
DefineMiddleware( | ||
TimeoutMiddleware, | ||
timeout=5, | ||
) | ||
] | ||
) |
8 changes: 8 additions & 0 deletions
8
docs/examples/middleware/middleware_protocol_migration_new.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from litestar.middleware import ASGIMiddleware | ||
from litestar.types import ASGIApp, Receive, Scope, Send | ||
|
||
|
||
class MyMiddleware(ASGIMiddleware): | ||
async def handle(self, scope: Scope, receive: Receive, send: Send, next_app: ASGIApp) -> None: | ||
# do stuff | ||
await next_app(scope, receive, send) |
11 changes: 11 additions & 0 deletions
11
docs/examples/middleware/middleware_protocol_migration_old.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
from litestar.middleware import MiddlewareProtocol | ||
from litestar.types import ASGIApp, Receive, Scope, Send | ||
|
||
|
||
class MyMiddleware(MiddlewareProtocol): | ||
def __init__(self, app: ASGIApp) -> None: | ||
self.app = app | ||
|
||
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: | ||
# do stuff | ||
await self.app(scope, receive, send) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import time | ||
|
||
from litestar.datastructures import MutableScopeHeaders | ||
from litestar.enums import ScopeType | ||
from litestar.middleware import ASGIMiddleware | ||
from litestar.types import ASGIApp, Message, Receive, Scope, Send | ||
|
||
|
||
class ProcessTimeHeader(ASGIMiddleware): | ||
scopes = (ScopeType.HTTP, ScopeType.ASGI) | ||
|
||
async def handle(self, scope: Scope, receive: Receive, send: Send, next_app: ASGIApp) -> None: | ||
start_time = time.monotonic() | ||
|
||
async def send_wrapper(message: Message) -> None: | ||
if message["type"] == "http.response.start": | ||
process_time = time.monotonic() - start_time | ||
headers = MutableScopeHeaders.from_message(message=message) | ||
headers["X-Process-Time"] = str(process_time) | ||
await send(message) | ||
|
||
await next_app(scope, receive, send_wrapper) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import anyio | ||
|
||
from litestar import Litestar, get | ||
from litestar.enums import ScopeType | ||
from litestar.exceptions import ClientException | ||
from litestar.middleware import ASGIMiddleware | ||
from litestar.types import ASGIApp, Receive, Scope, Send | ||
|
||
|
||
class TimeoutMiddleware(ASGIMiddleware): | ||
# we can configure some things on the class level here, related to when our | ||
# middleware should be applied. | ||
|
||
# if the requests' 'scope["type"]' is not "http", the middleware will be skipped | ||
scopes = (ScopeType.HTTP,) | ||
|
||
# if the handler for a request has set an opt of 'no_timeout=True', the middleware | ||
# will be skipped | ||
exclude_opt_key = "no_timeout" | ||
|
||
# the base class does not define an '__init__' method, so we're free to overwrite | ||
# this, which we're making use of to add some configuration | ||
def __init__( | ||
self, | ||
timeout: float, | ||
exclude_path_pattern: str | tuple[str, ...] | None = None, | ||
) -> None: | ||
self.timeout = timeout | ||
|
||
# we can also dynamically configure the options provided by the base class on | ||
# the instance level | ||
self.exclude_path_pattern = exclude_path_pattern | ||
|
||
async def handle(self, scope: Scope, receive: Receive, send: Send, next_app: ASGIApp) -> None: | ||
try: | ||
with anyio.fail_after(self.timeout): | ||
# call the next app in the chain | ||
await next_app(scope, receive, send) | ||
except TimeoutError: | ||
# if the request has timed out, raise an exception. since the whole | ||
# application is wrapped in an exception handling middleware, it will | ||
# transform this exception into a response for us | ||
raise ClientException(status_code=408) from None | ||
|
||
|
||
@get("/", no_timeout=True) | ||
async def handler_with_opt_skip() -> None: | ||
pass | ||
|
||
|
||
@get("/not-this-path") | ||
async def handler_with_path_skip() -> None: | ||
pass | ||
|
||
|
||
app = Litestar( | ||
route_handlers=[ | ||
handler_with_opt_skip, | ||
handler_with_path_skip, | ||
], | ||
middleware=[TimeoutMiddleware(timeout=5)], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.