Skip to content

blackbull.headers

blackbull.headers

Case-insensitive, ordered, multi-valued HTTP header store.

Provides:

  • Headers: satisfies the ASGI Iterable[tuple[bytes, bytes]] contract while adding get, getlist, case-insensitive lookup, append, and + concatenation.
  • HeaderList: type alias for Iterable[tuple[bytes, bytes]].

Headers

Ordered multi-valued HTTP header store.

Satisfies the ASGI Iterable[[byte string, byte string]] contract while also providing O(1) dict-like lookup.

Invariants:

  • Header names and values are always bytes (per ASGI spec).
  • Lookups are case-insensitive: the internal index is keyed on name.lower() (RFC 7230 §3.2 — header field names are case-insensitive). __contains__, __getitem__, getlist, and get all lowercase the requested name; iteration preserves the original casing of the input.
  • Insertion order of duplicate names is preserved (RFC 7230 §3.2.2).

Examples::

headers = Headers([(b'set-cookie', b'a=1'), (b'set-cookie', b'b=2')])

list(headers)
# [(b'set-cookie', b'a=1'), (b'set-cookie', b'b=2')]   # ASGI iteration

headers.getlist(b'set-cookie')
# [(b'set-cookie', b'a=1'), (b'set-cookie', b'b=2')]

headers.getlist(b'missing')
# []

headers.get(b'host')          # first value, or default
# b'localhost:8000'

__add__(other)

Return a new Headers containing all pairs from self then other.

__eq__(other)

Value equality on the ordered (name, value) pair list.

Two Headers are equal when they carry the same fields in the same order (RFC 7230 §3.2.2 — order is significant for repeated fields). Enables Connection round-trip equality (Sprint 79).

__getitem__(name)

Return all pairs for name. Raises KeyError if absent.

append(name_or_pairs, value=None)

Append header(s) to the end of the list.

Two-argument form: append(name, value) — adds a single pair. One-argument form: append(pairs) — adds every pair in the iterable.

get(name, default=b'')

Return the first value for name, or default if absent.

Mirrors dict.get(key, default): single value, optional default. For headers that may repeat use getlist(name).

get_sf_dict(name)

Parse name as a Structured Field Dictionary (RFC 9651).

Multiple field lines are combined first. Returns an ordered dict of member name → Item / Inner List, or None if the field is absent or fails strict parsing (per RFC 9651 §4.2 the whole field is then ignored).

Example::

headers.get_sf_dict(b'priority')      # {'u': (2, {}), 'i': (True, {})}

get_sf_item(name)

Parse name as a Structured Field Item (RFC 9651).

Returns (bare_item, parameters), or None if the field is absent or fails strict parsing (per RFC 9651 §4.2 the whole field is then ignored).

Example::

headers.get_sf_item(b'deprecation')   # (Date(1659578233), {})

get_sf_list(name)

Parse name as a Structured Field List (RFC 9651).

Multiple field lines are combined first. Returns a list of Items / Inner Lists, or None if the field is absent or fails strict parsing (per RFC 9651 §4.2 the whole field is then ignored).

Example::

headers.get_sf_list(b'accept-query')  # [('a', {}), ('b', {})]

getlist(name)

Return all pairs for name, or [] if the header is absent.