Repository navigation
serve_connection_with_upgrades does not enforce its timeout from initial connection, but initial data. #3756
Description
Activity
- addedC-bugCategory: bug. Something is wrong. This is bad!Category: bug. Something is wrong. This is bad!
on Sep 14, 2024 I suspect it's not the upgrades part, but rather the
autopart. Since it's doing an initial read to detect the HTTP version before passing on to the http1 state machine which knows about the timeout.after some further testing, that makes sense. Is this something that hyper-util concerns itself with? Is it not possible to do SlowLoris with HTTP/2.0 in some other way?
This still reproduces on hyper-util 0.1.20. The root cause is in the
autoserver builder's version sniffing:ReadVersion::poll(src/server/conn/auto/mod.rs) reads the H2 preface in a barepoll_readloop with no timeout, and it's driven before any handoff atlet (version, io) = ready!(read_version.poll(cx))?;.header_read_timeoutis configured on the inner http1 dispatcher, which only becomes active afterread_versionresolves. So a connection that sends no bytes parks in the sniff read indefinitely. Withserve_connection+http1_only()there's no sniff, which is why the timeout works there.
I'd like to fix this and see two reasonable approaches:
A. Contain it in hyper-util. Store a
Timerplus a read-version timeout on theauto::Builderand wrap theread_versionfuture in aSleep, failing the connection if the preface isn't received in time. Single-crate change, but it means either reusing the value set viahttp1().header_read_timeout()(not currently readable back from the inner builder) or introducing a dedicated knob.B. Expose it from hyper. Add getters on
http1::Builderfor the timer andheader_read_timeoutso hyper-util can apply the user's existingheader_read_timeoutto the sniff read directly. Cleaner semantics, but spans both crates and adds public API.Two questions before I open a PR:
- Should the sniff-phase timeout reuse
header_read_timeout, or be its own setting (e.g.read_version_timeout)? - Is a hyper-util-only change (A) preferred, or are you open to the small getter additions in hyper (B)?
Happy to implement whichever direction you prefer.
- addedK-hyper-utilCrate: hyper-utilCrate: hyper-utiland removedK-hyper-utilCrate: hyper-utilCrate: hyper-util
on Aug 31, 2026 - addedK-hyper-utilCrate: hyper-utilCrate: hyper-utiland removedK-hyper-utilCrate: hyper-utilCrate: hyper-util
on Sep 14, 2026 - addedE-pr-welcomeEffort: a pull request is welcome.Effort: a pull request is welcome.
on Oct 9, 2026 A different PR is welcome. Strong preference for human written communication
Sysinfo: Hyper 1.4.1 on
Darwin 23.6.0 root:xnu-10063.141.2~1/RELEASE_ARM64_T6020 arm64While l was looking into tokio-rs/axum#2741
I tried this code:
I expected a TCP connection opened to the server terminated after not sending data within one second, however, the connection was persisted indefinitely, and only terminated after some amount of data was sent. However, if instead of
serve_connection_with_upgrades,serve_connectionis used, andhttp1_only()is also set, Hyper exhibits the correct behavior