Skip to content

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'