Releases: nomasystems/nhttp_lib
Releases · nomasystems/nhttp_lib
Release list
v1.1.1
Fixed
- A release started with
-mode embeddedfailed to boot. The-on_load
functions ofnhttp_cookieandnhttp_h1callednhttp_headers, which
the boot loader reaches later in alphabetical order, so the call raised
undefandkerneldid not start. Both modules now compile their own
patterns from the octet sets insrc/nhttp_ascii.hrland call nothing
outside kernel and stdlib
Added
test/nhttp_load_SUITEholds the module load contract: no-on_load
function of this application calls another module of this application
Full Changelog: v1.1.0...v1.1.1
v1.1.0
Added
nhttp_h1:prepare_headers/1validates a header list once and returns a
block thatencode_request/2andencode_response/2reusenhttp_h1:encode_trailers/1andnhttp_h1:encode_response_head/4nhttp_h2:stream_stats/1reports the active, peer-opened, and peer-reset
stream countsmax_reset_streamsandmax_continuation_framesint:nhttp_h2:settings/0.
Both are local bounds and go on no wire.max_continuation_framesdefaults
to a value derived frommax_header_list_sizet:nhttp_ws_frame:frame_limits/0and the capped arities
nhttp_ws_frame:decode/2,decode_raw/3, anddecode_unmasked/2nhttp_headers:validate_field_name/1,validate_field_value/1,
lower_field_name/1,name_eq/2,is_token/1, andis_tchar/1
Changed
nhttp_h1:encode_request/1,2andnhttp_h1:encode_response/1,2return
{ok, iolist()} | {error, t:nhttp_h1:encode_error/0}. They returned
iolist()beforenhttp_cookie:encode_cookie/1andnhttp_cookie:encode_set_cookie/1return
{ok, binary()} | {error, _}, and the error names the class of the
violationnhttp_msg:build_response/2returns
{ok, response()} | {error, invalid_status | missing_status}nhttp_hpack:decode/2,3answers{invalid_field, Reason, State}, a shape
apart from the{error, Reason}of a decompression failure.Statecarries
every dynamic table update that the block asks for (RFC 9113 Section 4.3)nhttp_h1andnhttp_cookiescan with patterns that-on_loadcompiles
intopersistent_term, and the encode and parse paths build no intermediate
binary
Security
- Refuse a field name that is not a token, and a field value that carries CR,
LF, NUL, another control byte, or0x7F, at the HTTP/1.1 encoder. The
message is refused whole (RFC 9110 Sections 5.5 and 5.6.2, RFC 9112 Section
11.1). Response splitting and request smuggling (CVE-2020-11709,
CVE-2023-26130, CVE-2025-0825, CVE-2026-21428, CVE-2026-45372) - Validate a cookie name, a cookie value, a
Path, and aDomainagainst the
RFC 6265 Section 4.1.1 grammar on encode. No value is stripped, quoted, or
truncated (CVE-2020-11709, CVE-2023-26130, CVE-2025-0825, CVE-2026-21428,
CVE-2026-45372) - Read every literal field name and every literal field value in the HPACK and
the QPACK decoder. An uppercase name, an invalid octet, an interior colon, or
a value with leading or trailing whitespace is a stream error of type
PROTOCOL_ERROR on HTTP/2 and H3_MESSAGE_ERROR on HTTP/3 (RFC 9113 Section
8.2.1, RFC 9114 Section 4.1.2) - Combine every
Transfer-Encodingfield line into one coding list, and accept
the message only when that list holdschunkedonce, as the final coding
(RFC 9112 Sections 6.1 and 6.3). Refuse a chunk that does not end with CRLF
asincomplete_chunk, and refuse aContent-Lengthvalue that is not a run
of digits (CVE-2026-34441, CVE-2026-45352, CVE-2026-46527) - Refuse a declared WebSocket payload length above
max_frame_sizeas
{error, {frame_too_large, DeclaredLength}}, before the payload is buffered
(RFC 6455 Section 10.4).nhttp_wscaps at its maximum message size
(CVE-2025-46728, CVE-2025-53629) - Refuse a byte that follows a complete gzip or deflate stream as
{error, trailing_data}(CVE-2026-22776, CVE-2026-28435) - Count the streams that the peer opens and resets, and fail the connection
with ENHANCE_YOUR_CALM abovemax_reset_streams(CVE-2023-44487). Bound the
number of CONTINUATION frames in one field block (CVE-2026-29076) nhttp_msg:build_response/2never raises on peer input. A missing or
malformed:statusis a stream error (CVE-2026-31870)
Full Changelog: v1.0.5...v1.1.0
v1.0.5
Added
certs_keysclient TLS option innhttp_sock:build_client_ssl_opts/1and
t:nhttp_sock:connect_opts/0, forwarding in-memory client certificates for
mutual TLS (mTLS) without writing cert/key to disk
New Contributors
- @josecriane made their first contribution in #8
Full Changelog: v1.0.4...v1.0.5
v1.0.4
Added
nhttp_h1:encode_response/2takest:nhttp_h1:enc_opts/0.
#{content_length => omit}suppresses the automaticContent-Length
field. A server that answers aCONNECTrequest with a 2xx status uses
it, because RFC 9110 Section 8.6 forbids the field there and the response
map carries no request method
Fixed
nhttp_h1:encode_response/1emitsContent-Length: 0on a response with
an empty body. The call omitted the field before, so a client on a
persistent connection read the next response as contentnhttp_h1:encode_response/1emits noContent-Lengthat a 1xx, 204, or
304 status (RFC 9110 Section 8.6). At 304 the field is valid only at the
length that a 200 response carries, which the encoder cannot compute, so a
caller that knows the value supplies it in the header list
Full Changelog: 1.0.3...v1.0.4
v1.0.3
Added
nhttp_ws_frame:scan_utf8/1andnhttp_ws_frame:scan_utf8/2scan a run
of text for UTF-8 validity and return the trailing bytes that do not yet
form a character
Changed
nhttp_ws:decode_with_state/2returns{continue, Rest, Decoder}when it
consumes a non-final fragment. The call returned{more, 1, Decoder}
before, which hid the fact that the frame was consumed
Fixed
- Return the unconsumed rest of the buffer after a WebSocket fragment. A
caller that kept the whole buffer decoded the same fragment again and
failed withexpected_continuation - Validate a fragmented text message as UTF-8 (RFC 6455 §5.6) per fragment,
with the character that spans two frames carried across. A message that
ends with a truncated character is refused asinvalid_utf8
Full Changelog: v1.0.2...1.0.3
v1.0.2
Changed
- Listen sockets set
{send_timeout_close, true}so a send that hits
send_timeoutcloses the socket instead of leaving it half-dead
Fixed
- Reject an incomplete HTTP/1.1 request head as
header_too_largeonce
the buffered input exceedsmax_header_sizeplus an 8 KiB
request-line allowance, bounding both memory and the repeated rescan
of the unparsed tail - Apply the same
max_header_sizebudget to incomplete chunked trailer
sections - Reject chunk-size lines longer than 1 KiB as
invalid_chunk_size
Full Changelog: v1.0.1...v1.0.2
v1.0.1
What's Changed
- fix(h1): reject control chars in header values and spaces in the requ… by @mrrubinos in #1
New Contributors
- @mrrubinos made their first contribution in #1
Full Changelog: v1.0.0...v1.0.1
v1.0.0
Added
- HTTP/1.1 request and response codec (RFC 9110, RFC 9112)
- HTTP/2 connection and stream state machine (RFC 9113)
- HTTP/3 connection state machine, QUIC transport agnostic (RFC 9114)
- HPACK header compression (RFC 7541)
- QPACK header compression (RFC 9204)
- WebSocket frame codec (RFC 6455)
- Cookie parsing and encoding (RFC 6265)
- Content compression (gzip, deflate)
- Unified TCP/SSL socket abstraction with ALPN negotiation
- Sans-io design: pure functional state machines, no process spawning
- Property-based test suites backed by triq
- RFC 9110 and RFC 9112 compliance test suites
Full Changelog: https://github.com/nomasystems/nhttp_lib/commits/v1.0.0