Skip to content

blackbull.asgi

blackbull.asgi

ASGI protocol types: event-type string constants, typed message shapes, and typed event wrappers.

Three responsibilities, all framework-side:

  • ASGIEvent: namespace of ASGI 3.0 event-type strings, used for match/case dispatch and equality checks across both the framework and (importing from here) the server stack. Every constant is Final, so a type checker infers a Literal and comparisons against them narrow the event unions below.
  • The 19 TypedDict message shapes and the two direction unions (ASGIReceiveEvent / ASGISendEvent) plus the two channel callable aliases (ASGIReceiveCallable / ASGISendCallable). These are declarations only — erased at runtime, no wire or dispatch change.
  • ResponseStart / ResponseBody: dict-subclass wrappers for the two outgoing response event shapes so middleware can dispatch on Python type rather than string comparison. Both subclass dict so isinstance(e, dict) remains True — required for beartype and any ASGI send callable annotated event: dict.

Naming rule: an ASGI prefix marks boundary vocabulary and is quarantined to this module; unprefixed names (Connection, Headers, Request, Response) are BlackBull's native layer. The dicts on the channel are ASGI 3.0 events verbatim — the spec is free documentation for every key — so rg "from .asgi import" stays a literal map of the remaining ASGI surface.

ASGIEvent

Namespace for ASGI protocol event type strings (ASGI 3.0 spec).

HTTPDisconnectEvent

Bases: TypedDict

Client went away before the response completed.

HTTPRequestEvent

Bases: TypedDict

Incoming request body chunk.

HTTPResponseBodyEvent

Bases: TypedDict

Response body chunk; more_body keeps the response open.

HTTPResponsePathsendEvent

Bases: TypedDict

Hand a file path to the server to send (ASGI extension).

HTTPResponsePushEvent

Bases: TypedDict

HTTP/2 server push (ASGI extension, not baseline ASGI 3.0).

HTTPResponseStartEvent

Bases: TypedDict

Response status line + headers.

HTTPResponseTrailersEvent

Bases: TypedDict

Trailing headers, sent after the final body chunk.

LifespanShutdownCompleteEvent

Bases: TypedDict

Shutdown hooks finished successfully.

LifespanShutdownEvent

Bases: TypedDict

Server is stopping; run shutdown hooks.

LifespanShutdownFailedEvent

Bases: TypedDict

Shutdown hooks raised; message carries the reason.

LifespanStartupCompleteEvent

Bases: TypedDict

Startup hooks finished successfully.

LifespanStartupEvent

Bases: TypedDict

Server is starting; run startup hooks.

LifespanStartupFailedEvent

Bases: TypedDict

Startup hooks raised; message carries the reason.

ResponseBody

Bases: dict

http.response.body event with typed property access.

ResponseStart

Bases: dict

http.response.start event with typed property access.

WebSocketAcceptEvent

Bases: TypedDict

Complete the handshake.

WebSocketCloseEvent

Bases: TypedDict

Close the connection (app-initiated).

WebSocketConnectEvent

Bases: TypedDict

Handshake offered; the app answers with accept or close.

WebSocketDisconnectEvent

Bases: TypedDict

Connection closed (peer- or transport-initiated).

WebSocketReceiveEvent

Bases: TypedDict

One complete message from the client.

BlackBull's recipient always sets both keys, one of them None (FragmentAssembler has already reassembled any fragments), so the value types are optional rather than the keys being mutually exclusive.

WebSocketSendEvent

Bases: TypedDict

One complete message to the client.

parse_response_event(event)

Wrap event in the appropriate typed subclass for dispatch.

The returned object IS the event dict (shallow copy) — pass it directly to downstream send callables without re-serialisation. Trailers and unknown event types are returned unchanged.

ResponseStart/ResponseBody are dict subclasses, not statically members of ASGISendEvent; a caller threading the result back into a typed send callable casts at that seam (a runtime no-op) rather than widening the public union.