trillium-http-v1.3.5
·
18 commits
to main
since this release
The theme of this release is protocol correctness / conformance, with a focus on http/1.x.
Added
Headers::content_length()parses theContent-Lengthheader into anOption<u64>, accepting
only a single run of ASCII digits (rejecting a leading+/-, whichu64::from_strwould
otherwise accept, as well as multi-value, empty, and overflowing values). Prefer it over
get_str(ContentLength).and_then(|c| c.parse().ok()).
Changed
- The HTTP/1.x request parser is now trillium's own implementation; the
httparsedependency is
dropped and theparsecargo feature (which previously selected it) is retained as a no-op. The
new parser is stricter — it closes the conformance and security gaps below — but against
well-formed clients there is no observable difference.
Security
- HTTP/1.x request smuggling: a malformed
Content-Lengthwas previously coerced to a zero-length
body, leaving the declared bytes unread in the buffer. Obs-fold header continuations, control
characters in header values and request targets, non-token header names, and malformed chunk
framing were also accepted. All are now rejected, closing request-smuggling and parser-differential
vectors. - HTTP/1.1
Host: a request with noHost, more than one, or aHostcontaining userinfo, a path,
whitespace, or other illegal content is now rejected rather than routed.
Fixed
- Absolute-form request targets (
GET http://example.com/path) now route correctly; previously the
entire URI was treated as the request path. - A request carrying both an authority (
:authorityor absolute-form) and aHostthat differ only
by default port — e.g.example.com:443vsexample.com— is no longer spuriously rejected; the
two are compared under scheme-based normalization (all three protocols). - A chunked request body terminated by a bare LF after the last chunk no longer hangs the connection.
- Malformed HTTP/1.x requests now get a
400(or501for an unrecognized method) before the
connection closes, instead of being dropped without a response. An unhandledCONNECTnow defaults
to501rather than404. - A
Connection: closetoken split across multipleConnectionheader lines now closes the
connection as requested; previously the multi-line value was missed and the connection was kept
alive. - HTTP/2 and HTTP/3 now reject a malformed
Content-Lengthinstead of coercing it to a body length:
a malformed request earnsRST_STREAM(PROTOCOL_ERROR)(h2) /H3_MESSAGE_ERROR(h3), and a
malformed response on the client side earnsRST_STREAM(PROTOCOL_ERROR)(h2). Previously such a
value was silently treated as "no declared length," skipping the content-length / DATA
cross-check.