Skip to content

ASGI request scope

The framework-free middleware the Starlette and Litestar integrations specialise. See the request and response integrations for which module to install.

RequestScope

ASGI middleware that opens one depin async scope around every request.

Implemented directly against the ASGI protocol rather than a framework's HTTP-middleware base class, so streaming responses, server-sent events and WebSockets pass through without buffering. Every ASGI integration depin ships specialises this class, supplying only the seed that places its own framework's request object into the frame.

Connection scopes other than http and websocket are forwarded untouched, with no depin scope opened. The lifespan scope in particular is opened once at startup and lives for the whole process: wrapping it would leak a frame for the application's lifetime and put startup and shutdown inside a scope that never drains.

For the scopes it does wrap, the container is published to the request's context for the duration of the scope, so depin.hosted_container() reaches it from anywhere inside the request. The scope's teardowns run when the request ends — including when it ends by raising — and the publication is undone after them.

seed is applied to http connections only. A websocket connection has no request-body semantics, and the framework request classes the seeds construct are HTTP-shaped; a websocket therefore gets the scope and the published container, but no seeded request.

Parameters:

Name Type Description Default
app ASGIApp[ScopeT, ReceiveT, SendT]

The downstream ASGI application this middleware wraps.

required
container FrozenContainer

The frozen container to host for the duration of each request. Keyword-or-positional because the framework helpers that install middleware pass app positionally and container by keyword.

required
seed ScopeSeeder[ScopeT] | None

Called once per http connection, before the downstream application runs, to produce the key and value to place into the fresh scope frame. Returning None seeds nothing. Omitting it seeds nothing either.

None

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, per the wrapping framework's own idiom::

from depin import ScopeSeed

middleware = RequestScope(app, di, seed=lambda scope: ScopeSeed(Request, Request(scope)))

ASGIApp

Bases: Protocol

Any ASGI application or middleware: the downstream peer RequestScope wraps.

ASGIScope

ASGIScope = Mapping[str, object]

The connection scope: scope['type'] is 'http', 'websocket' or 'lifespan'.

Read-only, because that is the widest shape every framework's own scope type satisfies: a TypedDict is a collections.abc.Mapping but not a collections.abc.MutableMapping.

Receive

Bases: Protocol

The channel an ASGI application awaits to read the next inbound event.

Send

Bases: Protocol

The channel an ASGI application awaits to write one outbound event.

Message

Message = Mapping[str, object]

One ASGI event, in either direction.