blackbull.server.parser¶
blackbull.server.parser
¶
HTTP2DATAParser
¶
Bases: HTTP2ParserBase
Parses an HTTP/2 DATA frame. Currently returns a fresh empty ASGI scope;
body bytes are delivered via HTTP2Recipient rather than this parser.
HTTP2HEADParser
¶
Bases: HTTP2ParserBase
Parses an HTTP/2 HEADERS frame into an ASGI http scope dict.
Pulls :method / :path / :scheme from the frame's pseudo-headers,
encodes the regular headers as bytes pairs into a Headers object,
and resolves root_path from the X-Forwarded-Prefix header.
HTTP2ParserBase
¶
Abstract base for HTTP/2 frame parsers that build an ASGI scope.
Subclasses set FRAME_TYPE to the FrameTypes value they handle and
implement parse(). __init_subclass__ auto-registers each concrete
subclass in _registry so ParserFactory.Get can dispatch by frame type.
Setting FRAME_TYPE = None keeps a class abstract (skipped at registration).
ParserFactory
¶
Dispatches an incoming HTTP/2 frame to the parser registered for its type.
Each HTTP2ParserBase subclass registers itself in
HTTP2ParserBase._registry keyed on its FRAME_TYPE;
Get(frame, stream) looks up that registry and instantiates the matching
parser bound to the given stream.
parse_headers(frame)
¶
Build an ASGI http (or websocket) scope from a HEADERS frame.
Hot path on every request — kept as a module-level function so that
callers avoid the dict-lookup + parser allocation that ParserFactory
requires.
Also performs request-level pseudo-header presence checks (RFC 9113
§8.3.1). Field-level checks already happened in parse_payload; if
that flagged frame.malformed we still build a scope to keep the
contract simple but the actor will discard it before dispatch. If
parse_headers itself finds a missing or empty required pseudo, it sets
frame.malformed so the same actor check rejects the request.