trillium-client-v0.9.5
·
18 commits
to main
since this release
The theme of this release is protocol correctness / conformance, with a focus on http/1.x.
Changed
- The trillium HTTP/1.x response parser (formerly behind the
parsefeature) is now the exclusive
HTTP/1.x parser; the httparse-backed path has been removed and thehttparsedependency
dropped. Theparsecargo feature is retained as a no-op for semver compatibility (it still
forwards to the matching no-op feature in trillium-http).
Security
- HTTP/1.x response smuggling: a malformed or duplicated
Content-Lengthin a response was
previously coerced — a non-digit value (including a leading+, which the standard library parses)
or more than oneContent-Lengthheader silently fell back to read-to-close framing instead of
being rejected. Because this client backs trillium-proxy, that framing disagreement with an
upstream or downstream that trusts the literalContent-Lengthis a response-smuggling / desync
vector. Such responses are now rejected, sharing the exact validation the server uses for request
Content-Lengthso both halves of a proxy parse identically. The HTTP/3 client response path now
applies the sameContent-Lengthvalidation. Transfer-Encodingframing is now strict and consistent. The only transfer-coding trillium
decodes ischunked, so a response'sTransfer-Encodingmust be exactly a singlechunked;
anything else — a coding list (gzip, chunked), a repeatedchunked(which RFC 9112 §6.1 forbids
a sender from producing),chunkednot the final coding, or a value split across multiple header
lines — is now rejected. Previously some of these were accepted and then mis-framed (decoded once,
or silently downgraded to read-to-close), a framing/validation disagreement that is a
response-smuggling vector. This matches the server's request-sideTransfer-Encodingrule.
Fixed
- A
Connection: closesplit across multipleConnectionheader lines was ignored when deciding
whether to reuse the connection, so the transport could be pooled and reused even though the peer
asked to close it. AllConnectionlines and tokens are now scanned. - A response status-line with a malformed status-code — more than three digits (
HTTP/1.1 2000 OK)
or otherwise not terminated by a space or end-of-line after three digits — is now rejected instead
of being silently truncated to the first three digits. - Regression: HTTP/1.1 responses are treated as keep-alive unless either side sends
Connection: close
(a 1.0 response still requires an explicitConnection: keep-aliveon both sides). Previously reuse
required an explicitConnection: keep-aliveeven on 1.1, so the overwhelming majority of 1.1
connections were closed and reopened instead of pooled. - A connection abandoned before its response head arrived — a timeout or transport error
mid-request — is no longer returned to the pool, where the next request could reuse the
half-spent transport. - The network response head now replaces, rather than merges with, any response headers a handler
set synthetically before the round-trip (e.g. aContent-Lengthfromset_response_body), so the
parsed response can't end up with duplicated headers.