nhttp_headers (nhttp_lib v1.1.1)
View SourceProtocol-agnostic header utilities.
Headers carried by nhttp_lib:headers/0 are an ordered list of
{Name, Value} binary pairs. The codec layers write names in lowercase
at parse time. This module stores the name that the caller gives and
never rewrites it. append/3 and set/3 store the lowercase form of
the name that they add, and leave every other entry alone.
Key invariants:
- Header names compare case-insensitively (RFC 9110 §5.1). A lookup
matches a stored name in any case, so
get/2with<<"content-length">>finds a storedContent-Length. - Multi-valued headers keep insertion order.
get/2,3returns the first match.delete/2removes every occurrence.append/3appends and keeps existing entries.
The module also holds one definition of the field validity rule that
RFC 9113 §8.2.1 and RFC 9114 §4.1.2 state for a receiver:
validate_field_name/1, validate_field_value/1 and the wire
lowercasing of lower_field_name/1.
Summary
Functions
Append {Name, Value} to the end of the headers list, preserving any
existing occurrences. Useful for multi-valued headers such as
set-cookie. The name is stored lowercase.
Remove every header whose name matches Name. Case-insensitive.
The compiled pattern that matches every octet that RFC 9110 §5.5 forbids
in a field value: 0x00-0x1F except 0x09, and 0x7F.
A caller that scans many field values reads the pattern once and passes
it to binary:match/2 for each one.
Keep only the headers for which Pred(Name, Value) returns true.
Order is preserved.
Get the first value for Name, or undefined if absent. Case-insensitive.
Get the first value for Name, or Default if absent. Case-insensitive.
True iff a header with the given name exists. Case-insensitive.
True iff Value holds an octet that RFC 9110 §5.5 forbids in a field
value: 0x00-0x1F except 0x09, or 0x7F.
The scan reads seven octets at a time and charges one reduction per call,
so it holds a constant cost per octet at every length.
field_value_bad_pattern/0 with binary:match/2 is cheaper below about a
hundred octets, because binary:match/2 charges one reduction per ten
octets up to its trap. A caller that scans values of any length picks
between the two on byte_size/1.
True iff C is a tchar, the character set that RFC 9110 §5.6.2 allows
in a token.
RFC 6265 §4.1.1 defines cookie-name in terms of the RFC 2616 §2.2
token, which admits the same octets, so cookie names are checked with
this predicate too.
True iff Bin is a token per RFC 9110 §5.6.2: token = 1*tchar. An
empty binary is not a token.
Lowercase a field name for the wire, without a copy when the name already
holds no uppercase octet.
RFC 9114 §4.2 requires that characters in field names are converted to
lowercase before their encoding, and RFC 9113 §8.2.1 forbids 0x41-0x5A
in a field name on the wire. The scan runs before the copy, so a name
that is already lowercase comes back as the very binary that the caller
passed in.
Non-ASCII upper-half octets pass through unchanged, as they do in
to_lower/1. This function does not validate the name. Pair it with
validate_field_name/1 when the name arrives from a peer.
True iff two field names name the same field. Field names compare
case-insensitively (RFC 9110 §5.1), so <<"Content-Length">> and
<<"content-length">> name the same field.
A caller that asks about a fixed set of names walks the list once and
compares each stored name with this function.
The compiled pattern that matches every octet that is not a tchar.
A caller that scans many tokens reads the pattern once and passes it to
binary:match/2 for each one.
Replace every occurrence of Name with a single {Name, Value} entry.
The name is stored lowercase. The replacement is appended to the end of
the headers list when no prior occurrence exists.
Lowercase an ASCII binary using HTTP header semantics. RFC 9110 §5.1: field names are ASCII, so non-ASCII upper-half bytes pass through unchanged.
Validate a field name against the minimal rule that RFC 9113 §8.2.1
states as a MUST, and that RFC 9114 §4.1.2 repeats for HTTP/3.
A field name must not hold an octet in 0x00-0x20, 0x41-0x5A or
0x7F-0xFF. A field name must not hold a colon, except the single
leading colon of a pseudo-header field (RFC 9113 §8.3). An empty name,
and a name that is a bare colon and therefore names no pseudo-header
field, are refused as empty_field_name.
uppercase_field_name names the case that RFC 9114 §4.1.2 lists apart
from the other invalid characters. It is reported when the first
offending octet is in 0x41-0x5A.
This is the minimal rule, not the token rule of RFC 9110 §5.6.2, which
RFC 9113 §8.2.1 states as a SHOULD. Use is_token/1 for the stricter
test.
Validate a field value against RFC 9110 §5.5 and the edge whitespace rule
that RFC 9113 §8.2.1 states as a MUST.
The refused octet set is 0x00-0x1F except 0x09, plus 0x7F. That set
is a superset of the NUL, LF and CR that RFC 9113 §8.2.1 names, because
RFC 9113 §8.2.1 asks for validation against RFC 9110 §5.5. A value that
starts or ends with SP or HTAB is refused as field_value_edge_whitespace,
which field-content of RFC 9110 §5.5 forbids and RFC 9113 §8.2.1 states
again. An empty value is accepted, because field-value of RFC 9110 §5.5
is *field-content.
Types
Functions
-spec append(binary(), binary(), nhttp_lib:headers()) -> nhttp_lib:headers().
Append {Name, Value} to the end of the headers list, preserving any
existing occurrences. Useful for multi-valued headers such as
set-cookie. The name is stored lowercase.
-spec delete(binary(), nhttp_lib:headers()) -> nhttp_lib:headers().
Remove every header whose name matches Name. Case-insensitive.
-spec field_value_bad_pattern() -> binary:cp().
The compiled pattern that matches every octet that RFC 9110 §5.5 forbids
in a field value: 0x00-0x1F except 0x09, and 0x7F.
A caller that scans many field values reads the pattern once and passes
it to binary:match/2 for each one.
-spec filter(fun((binary(), binary()) -> boolean()), nhttp_lib:headers()) -> nhttp_lib:headers().
Keep only the headers for which Pred(Name, Value) returns true.
Order is preserved.
-spec get(binary(), nhttp_lib:headers()) -> binary() | undefined.
Get the first value for Name, or undefined if absent. Case-insensitive.
-spec get(binary(), nhttp_lib:headers(), Default) -> binary() | Default.
Get the first value for Name, or Default if absent. Case-insensitive.
-spec has(binary(), nhttp_lib:headers()) -> boolean().
True iff a header with the given name exists. Case-insensitive.
True iff Value holds an octet that RFC 9110 §5.5 forbids in a field
value: 0x00-0x1F except 0x09, or 0x7F.
The scan reads seven octets at a time and charges one reduction per call,
so it holds a constant cost per octet at every length.
field_value_bad_pattern/0 with binary:match/2 is cheaper below about a
hundred octets, because binary:match/2 charges one reduction per ten
octets up to its trap. A caller that scans values of any length picks
between the two on byte_size/1.
True iff C is a tchar, the character set that RFC 9110 §5.6.2 allows
in a token.
RFC 6265 §4.1.1 defines cookie-name in terms of the RFC 2616 §2.2
token, which admits the same octets, so cookie names are checked with
this predicate too.
True iff Bin is a token per RFC 9110 §5.6.2: token = 1*tchar. An
empty binary is not a token.
Lowercase a field name for the wire, without a copy when the name already
holds no uppercase octet.
RFC 9114 §4.2 requires that characters in field names are converted to
lowercase before their encoding, and RFC 9113 §8.2.1 forbids 0x41-0x5A
in a field name on the wire. The scan runs before the copy, so a name
that is already lowercase comes back as the very binary that the caller
passed in.
Non-ASCII upper-half octets pass through unchanged, as they do in
to_lower/1. This function does not validate the name. Pair it with
validate_field_name/1 when the name arrives from a peer.
True iff two field names name the same field. Field names compare
case-insensitively (RFC 9110 §5.1), so <<"Content-Length">> and
<<"content-length">> name the same field.
A caller that asks about a fixed set of names walks the list once and
compares each stored name with this function.
-spec non_tchar_pattern() -> binary:cp().
The compiled pattern that matches every octet that is not a tchar.
A caller that scans many tokens reads the pattern once and passes it to
binary:match/2 for each one.
-spec set(binary(), binary(), nhttp_lib:headers()) -> nhttp_lib:headers().
Replace every occurrence of Name with a single {Name, Value} entry.
The name is stored lowercase. The replacement is appended to the end of
the headers list when no prior occurrence exists.
Lowercase an ASCII binary using HTTP header semantics. RFC 9110 §5.1: field names are ASCII, so non-ASCII upper-half bytes pass through unchanged.
-spec validate_field_name(binary()) -> ok | {error, field_name_error()}.
Validate a field name against the minimal rule that RFC 9113 §8.2.1
states as a MUST, and that RFC 9114 §4.1.2 repeats for HTTP/3.
A field name must not hold an octet in 0x00-0x20, 0x41-0x5A or
0x7F-0xFF. A field name must not hold a colon, except the single
leading colon of a pseudo-header field (RFC 9113 §8.3). An empty name,
and a name that is a bare colon and therefore names no pseudo-header
field, are refused as empty_field_name.
uppercase_field_name names the case that RFC 9114 §4.1.2 lists apart
from the other invalid characters. It is reported when the first
offending octet is in 0x41-0x5A.
This is the minimal rule, not the token rule of RFC 9110 §5.6.2, which
RFC 9113 §8.2.1 states as a SHOULD. Use is_token/1 for the stricter
test.
-spec validate_field_value(binary()) -> ok | {error, field_value_error()}.
Validate a field value against RFC 9110 §5.5 and the edge whitespace rule
that RFC 9113 §8.2.1 states as a MUST.
The refused octet set is 0x00-0x1F except 0x09, plus 0x7F. That set
is a superset of the NUL, LF and CR that RFC 9113 §8.2.1 names, because
RFC 9113 §8.2.1 asks for validation against RFC 9110 §5.5. A value that
starts or ends with SP or HTAB is refused as field_value_edge_whitespace,
which field-content of RFC 9110 §5.5 forbids and RFC 9113 §8.2.1 states
again. An empty value is accepted, because field-value of RFC 9110 §5.5
is *field-content.