Litestar integration¶
RequestScope ¶
Bases: RequestScope[Scope, Receive, Send]
ASGI middleware that opens a depin async scope around every Litestar request.
Implemented directly against the ASGI protocol (not a Litestar middleware base class) so streaming responses, server-sent events, and WebSockets pass through without buffering.
The container is published to the connection's context for the duration of
the scope, so depin.hosted_container() reaches it from anywhere inside
the request.
Only http and websocket connections reach it. Litestar answers the
lifespan scope inside Litestar.__call__, above its middleware stack, so
unlike the Starlette integration this one is never handed one — which is
why the connection triple it is typed against is Scope, Litestar's
union of the two connection scopes, and a lifespan scope would not
type-check as an argument to it. A websocket is scoped and hosted exactly
like an HTTP request, but it is not seeded, because it has no request-body
semantics and litestar.Request is HTTP-shaped.
For HTTP requests it places a litestar.Request into the active scope
frame, under the key Request[object, object, State], so scoped
providers can read headers, URL, cookies, and state.
Do not read the body through that request. It carries no receive channel,
so it can never take the body from the route handler — but unlike the
Starlette seed it does not reliably raise either, because
litestar.Request caches the body on ScopeState, which belongs to the
connection scope and is therefore shared with the request Litestar builds
for the handler. A read before anything has parsed the body raises
RuntimeError from empty_receive; a read from a handler that declares
a data parameter returns the body Litestar has already parsed, with no
error at all. Treat the body as a typed route parameter, not a provider
input.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app
|
ASGIApp
|
The downstream ASGI application this middleware wraps. Litestar supplies it by keyword, so the parameter must stay keyword-usable. |
required |
container
|
FrozenContainer
|
The frozen container to host for the duration of each request. |
required |
Raises:
| Type | Description |
|---|---|
ExceptionGroup
|
One or more teardowns failed when the request's scope closed. Every failure is included; one does not hide another. |
Example
Install the middleware once, wrapped so the container reaches the
constructor Litestar calls with app=::
app = Litestar(
route_handlers=[handler],
middleware=[DefineMiddleware(RequestScope, container=di)],
)
seed_request ¶
seed_request(scope: Scope) -> ScopeSeed
Build the litestar.Request that RequestScope places into each HTTP frame.
The request is constructed from the connection scope alone, so the body
must not be read through it: see RequestScope for what such a read does
and why.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scope
|
Scope
|
The ASGI connection scope of the request being opened. |
required |
Returns:
| Type | Description |
|---|---|
ScopeSeed
|
The key to bind the request under, and the request itself. |
Example
scope = { ... 'type': 'http', ... 'method': 'POST', ... 'path': '/orders', ... 'headers': [(b'x-tenant', b'acme')], ... } seed = seed_request(scope) seed.key == Request[object, object, State] True seed.value.headers['x-tenant'] 'acme'