Skip to content

Contribute our CONNECT tunnel fixes to hyper-util #702

Description

@wkirschenmann

The Rust transport carries its own HTTP CONNECT tunnel rather than using
hyper_util::client::legacy::connect::proxy::Tunnel, for two defects in hyper-util 0.1.20, the latest
published version. Both are ours to fix upstream rather than to work around forever.

A status line split across reads fails a good tunnel. On the first read, tunnel.rs:216:

let recvd = &buf[..pos];
if recvd.starts_with(b"HTTP/1.1 200") || recvd.starts_with(b"HTTP/1.0 200") { ... }
else if recvd.starts_with(b"HTTP/1.1 407") { return Err(TunnelError::ProxyAuthRequired); }
else { return Err(TunnelError::TunnelUnsuccessful); }

"HTTP/1.1 2" matches neither prefix and lands in the last arm, so a successful CONNECT is rejected
because the bytes arrived in two segments. Legal, and likelier with a slow proxy or a small MSS.
hyperium/hyper-util#300 fixes this. It is open, unmerged and unreleased; follow it rather than duplicate
it.

Only 200 opens the tunnel. RFC 9110 says any 2xx switches a CONNECT connection to tunnel mode. A
proxy answering 201 gets TunnelError::TunnelUnsuccessful. Nothing upstream covers this; we should
open the pull request.

Ours reads to the blank line before parsing and accepts any 2xx, and both behaviours are covered by
integration tests against a real proxy.

Done when both are released upstream. Deleting ours is then tracked by #699.

Measured, not just read

Driving Tunnel against a fake proxy, with an unsplit 200 as the control:

plain 200: ACCEPTED, as it should be
201: REFUSED with `tunnel error: unsuccessful`
split: REFUSED with `tunnel error: unsuccessful`

The split case writes HTTP/1.1 2, waits 50ms, then the rest. Both defects are on hyper-util's main
branch today, not only in the published 0.1.20.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions