without_asgi¶
without adapters that turn an ASGI app's receive/send into typed event streams and back.
without_asgi
¶
LifespanReply
¶
LifespanReply = (
StartupComplete
| ShutdownComplete
| StartupFailed
| ShutdownFailed
)
Outbound
¶
Outbound = (
ResponseStart
| ResponseBody
| ServerPush
| ZeroCopySend
| PathSend
| EarlyHint
| ResponseTrailers
| ResponseDebug
)
WebsocketOutbound
¶
WebsocketOutbound = (
WebsocketAccept
| WebsocketSend
| WebsocketClose
| WebsocketResponseStart
| WebsocketResponseBody
)
RequestBody
dataclass
¶
WebsocketConnect
dataclass
¶
The client is opening a websocket and awaiting an accept or a close.
WebsocketDisconnect
dataclass
¶
EarlyHint
dataclass
¶
Response
dataclass
¶
Response(
status: int, headers: RawHeaders = (), body: bytes = b""
)
ResponseBody
dataclass
¶
ResponseDebug
dataclass
¶
ResponseStart
dataclass
¶
ResponseStart(
status: int,
headers: RawHeaders = (),
trailers: bool = False,
)
ResponseTrailers
dataclass
¶
ResponseTrailers(
headers: RawHeaders, more_trailers: bool = False
)
Trailing headers sent after the final body (http.response.trailers extension).
ServerPush
dataclass
¶
ServerPush(path: str, headers: RawHeaders)
An HTTP/2 server push (http.response.push extension).
SupportsFileno
¶
WebsocketAccept
dataclass
¶
WebsocketAccept(
subprotocol: str | None = None, headers: RawHeaders = ()
)
WebsocketClose
dataclass
¶
Close a websocket connection, or reject it when sent before WebsocketAccept.
code is a
WebSocket close code;
1000 is a normal closure. If sent before the handshake is accepted, the
server discards code/reason and returns an HTTP 403 instead, so these
only reach the client on a close after accept.
WebsocketResponseBody
dataclass
¶
WebsocketResponseStart
dataclass
¶
WebsocketResponseStart(
status: int, headers: RawHeaders = ()
)
The start of an HTTP denial response (websocket.http.response extension).
ZeroCopySend
dataclass
¶
ZeroCopySend(
file: SupportsFileno,
offset: int | None = None,
count: int | None = None,
more_body: bool = False,
)
A zero-copy file-descriptor send (http.response.zerocopysend extension).
The application is responsible for closing file afterwards.
Asgi
dataclass
¶
HttpScope
dataclass
¶
HttpScope(
asgi: Asgi,
http_version: str,
method: str,
scheme: str,
path: str,
raw_path: bytes | None,
query_string: bytes,
root_path: str,
headers: RawHeaders,
client: tuple[str, int] | None,
server: tuple[str, int | None] | None,
extensions: Mapping[str, Mapping[str, object]] | None,
)
The per-request connection facts, known once when the request opens.
Field descriptions are taken from the ASGI HTTP connection scope: https://asgi.readthedocs.io/en/latest/specs/www.html#http-connection-scope
The ASGI state namespace is intentionally not surfaced: without threads
lifespan-derived state to handlers explicitly through make_asgi_app, rather
than reading it from the scope.
scheme
instance-attribute
¶
scheme: str
URL scheme portion (likely "http" or "https"); defaults to "http".
path
instance-attribute
¶
path: str
HTTP request target excluding any query string, with percent-encoded sequences and UTF-8 byte sequences decoded into characters.
raw_path
instance-attribute
¶
raw_path: bytes | None
The original HTTP path component as the bytes the web server received,
excluding any query string; None if the server cannot provide it.
root_path
instance-attribute
¶
root_path: str
The root path this application is mounted at (WSGI SCRIPT_NAME);
defaults to "".
headers
instance-attribute
¶
headers: RawHeaders
[name, value] byte-string header pairs, in the order received;
duplicates are preserved.
client
instance-attribute
¶
Remote [host, port]; None if not provided.
server
instance-attribute
¶
Server [host, port], or [path, None] for a unix socket; None if not
provided.
LifespanScope
dataclass
¶
LifespanScope(asgi: Asgi)
The server lifecycle scope, shared across the whole event loop.
Field descriptions are taken from the ASGI lifespan scope: https://asgi.readthedocs.io/en/latest/specs/lifespan.html#scope
The ASGI state namespace is intentionally not surfaced: without threads
lifespan-derived state to handlers explicitly through make_asgi_app (which
holds it in a _Cell and passes it per request), rather than via the scope.
Tls
dataclass
¶
Tls(
server_cert: str | None,
client_cert_chain: tuple[str, ...],
client_cert_name: str | None,
client_cert_error: str | None,
tls_version: int | None,
cipher_suite: int | None,
)
The tls extension's connection info, present only on TLS connections.
Field descriptions are taken from the ASGI TLS extension: https://asgi.readthedocs.io/en/latest/specs/tls.html
server_cert
instance-attribute
¶
server_cert: str | None
PEM-encoded server certificate; None if the server cannot provide it.
client_cert_chain
instance-attribute
¶
PEM-encoded client certificate chain (client cert first); empty if none.
client_cert_name
instance-attribute
¶
client_cert_name: str | None
RFC4514 Distinguished Name of the client certificate subject; None if
no client certificate.
client_cert_error
instance-attribute
¶
client_cert_error: str | None
Verification error message if a client certificate failed validation;
None if it verified or none was provided.
WebsocketScope
dataclass
¶
WebsocketScope(
asgi: Asgi,
http_version: str,
scheme: str,
path: str,
raw_path: bytes | None,
query_string: bytes,
root_path: str,
headers: RawHeaders,
client: tuple[str, int] | None,
server: tuple[str, int | None] | None,
subprotocols: tuple[str, ...],
extensions: Mapping[str, Mapping[str, object]] | None,
)
The handshake facts of a websocket connection, known when it opens.
Field descriptions are taken from the ASGI WebSocket connection scope: https://asgi.readthedocs.io/en/latest/specs/www.html#websocket-connection-scope
The ASGI state namespace is intentionally not surfaced: without threads
lifespan-derived state to handlers explicitly through make_asgi_app, rather
than reading it from the scope.
scheme
instance-attribute
¶
scheme: str
URL scheme portion (likely "ws" or "wss"); defaults to "ws".
path
instance-attribute
¶
path: str
HTTP request target excluding any query string, with percent-encoded sequences and UTF-8 byte sequences decoded into characters.
raw_path
instance-attribute
¶
raw_path: bytes | None
The original HTTP path component as the bytes the web server received,
excluding any query string; None if the server cannot provide it.
root_path
instance-attribute
¶
root_path: str
The root path this application is mounted at (WSGI SCRIPT_NAME);
defaults to "".
headers
instance-attribute
¶
headers: RawHeaders
[name, value] byte-string header pairs, in the order received;
duplicates are preserved.
client
instance-attribute
¶
Remote [host, port]; None if not provided.
server
instance-attribute
¶
Server [host, port], or [path, None] for a unix socket; None if not
provided.
subprotocols
instance-attribute
¶
Subprotocols the client advertised; defaults to empty.
ClientDisconnect
¶
Bases: Exception
The client disconnected before its request body was fully received.
make_asgi_app
¶
make_asgi_app(
lifespan: Lifespan[T],
http: HttpRouter[T] = refuse_http,
websocket: WebsocketRouter[T] = refuse_websocket,
) -> ASGIApp
Build the ASGI app that drives lifespan and runs a per-connection
Processor over each connection's event stream.
This is the ASGI entrypoint: it parses each raw scope into its typed value
and owns all the receive/send wiring. The lifespan scope is set up once on
startup and torn down on shutdown, with boot failures reported as
lifespan.startup.failed / lifespan.shutdown.failed. For a connection
scope it calls the matching handler with the state threaded in, wraps
receive into the inbound event stream, runs the returned Processor, and
drains its outbound stream into send: the handler only ever sees streams.
Each protocol's router defaults to one that refuses the connection, so an app
serves a protocol only by passing its own router (an HTTP-only app passes
http, a WebSocket-only app passes websocket). The default refusal never
reaches app code: an HTTP scope gets a 501 Not Implemented response, a
WebSocket scope is closed before accept (which the server turns into a
403). Drilling under this driver, e.g. to build a handler that needs the raw
receive/send, is parse_scope plus the http_inbound / http_outbound
(and websocket) shell functions this wires together.
refuse_http
¶
refuse_http(state: object, head: HttpScope) -> HttpHandler
An HttpRouter that refuses every request with 501 Not Implemented.
refuse_websocket
¶
refuse_websocket(
state: object, head: WebsocketScope
) -> WebsocketHandler
A WebsocketRouter that refuses every connection by closing before accept (a 403).
encode_inbound
¶
encode_inbound(event: Inbound) -> RawMessage
Render one inbound http event as the raw dict an ASGI receive returns.
The server-direction dual of parse_inbound: a transport that owns the wire
(without-http) builds typed Inbound events and hands them to the app as the
dicts ASGI receive yields.
encode_lifespan_event
¶
encode_lifespan_event(event: LifespanEvent) -> RawMessage
Render one lifespan event as the raw dict an ASGI receive returns.
encode_websocket_inbound
¶
encode_websocket_inbound(
event: WebsocketInbound,
) -> RawMessage
Render one inbound websocket event as the raw dict an ASGI receive returns.
parse_inbound
¶
parse_inbound(message: RawMessage) -> Inbound
Classify one inbound http event. An unknown event is a protocol fault, so it raises.
parse_lifespan_event
¶
parse_lifespan_event(message: RawMessage) -> LifespanEvent
Classify one lifespan event. An unknown event is a protocol fault, so it raises.
parse_websocket_inbound
¶
parse_websocket_inbound(
message: RawMessage,
) -> WebsocketInbound
Classify one inbound websocket event. An unknown event is a protocol fault, so it raises.
encode_lifespan_reply
¶
encode_lifespan_reply(reply: LifespanReply) -> RawMessage
Render one lifespan reply as the raw dict an ASGI send expects.
encode_outbound
¶
encode_outbound(event: Outbound) -> RawMessage
Render one outbound http event as the raw dict an ASGI send expects.
encode_response
¶
Split a whole Response into its ResponseStart then final ResponseBody.
encode_websocket_outbound
¶
encode_websocket_outbound(
event: WebsocketOutbound,
) -> RawMessage
Render one outbound websocket event as the raw dict an ASGI send expects.
parse_lifespan_reply
¶
parse_lifespan_reply(message: RawMessage) -> LifespanReply
Classify one lifespan reply from the raw dict an app passed to send.
parse_outbound
¶
parse_outbound(message: RawMessage) -> Outbound
Classify one outbound http event from the raw dict an app passed to send.
The server-direction dual of encode_outbound: a transport that owns the wire
(without-http) reads the dicts the app sends and parses them into typed
Outbound events at the boundary. An unknown event is a protocol fault, so it
raises.
parse_websocket_outbound
¶
parse_websocket_outbound(
message: RawMessage,
) -> WebsocketOutbound
Classify one outbound websocket event from the raw dict an app passed to send.
encode_http_scope
¶
Render a typed HttpScope as the raw http scope dict an ASGI app expects.
The server-direction dual of parse_http_scope: a transport that owns the
wire (without-http) builds the typed scope from the request line and renders
it back to the dict the ASGI contract hands an app.
encode_scope
¶
Render any typed scope as its raw ASGI dict, the dual of parse_scope.
encode_websocket_scope
¶
encode_websocket_scope(scope: WebsocketScope) -> RawScope
Render a typed WebsocketScope as the raw websocket scope dict an ASGI app expects.
extension
¶
extension(
extensions: Mapping[str, Mapping[str, object]] | None,
name: str,
) -> Mapping[str, object] | None
The named extension's advertised options, or None when it is absent.
Parse, don't validate: this returns the options mapping itself (often empty,
as for http.response.trailers) rather than a bool, so a caller needing the
options has them and one needing only presence checks is not None.
Server-advertised extensions are optional per-connection capabilities; an app
negotiates by looking one up before using it and falling back when it is
None (and parse_tls reads the tls extension through this).
parse_http_scope
¶
Read an http scope into the typed connection facts, validating at the boundary.
parse_scope
¶
Classify any scope by its type discriminator. An unknown type is a protocol fault, so it raises.
parse_tls
¶
Read the tls extension's connection info from a scope's extensions.
Returns None when the connection is not over TLS (the extension is absent),
which is how an application distinguishes TLS from plaintext connections.
parse_websocket_scope
¶
parse_websocket_scope(scope: RawScope) -> WebsocketScope
Read a websocket scope into the typed handshake facts, validating at the boundary.
http_inbound
async
¶
http_inbound(receive: Receive) -> AsyncIterator[Inbound]
An http request's inbound events as a stream.
The stream ends when the request is fully received (the last body chunk, or a disconnect), so a downstream processor's input runs dry exactly when the request does: the request's lifecycle is this stream's lifecycle.
http_outbound
¶
A sink that writes each outbound event to ASGI send, encoding at the boundary.
lifespan_inbound
async
¶
lifespan_inbound(
receive: Receive,
) -> AsyncIterator[LifespanEvent]
The lifespan protocol's events as a stream, ending after shutdown.
lifespan_outbound
¶
lifespan_outbound(send: Send) -> Sink[LifespanReply]
A sink that writes each lifespan reply to ASGI send, encoding at the boundary.
read_body
async
¶
Accumulate an http request's body across its RequestBody chunks.
Raises ClientDisconnect if the client goes away before the final chunk,
so a truncated body fails loudly rather than passing for a complete one.
websocket_inbound
async
¶
websocket_inbound(
receive: Receive,
) -> AsyncIterator[WebsocketInbound]
A websocket connection's inbound events as a stream.
The stream ends on WebsocketDisconnect, so the connection's lifecycle is
this stream's lifecycle, the same shape as http_inbound.
websocket_outbound
¶
websocket_outbound(send: Send) -> Sink[WebsocketOutbound]
A sink that writes each outbound websocket event to ASGI send, encoding at the boundary.