hyperium / hyper

An HTTP library for Rust
https://hyper.rs
MIT License
14.08k stars 1.55k forks source link

hyper-util auto version detection breaks the ability to use `Upgraded::downcast` #3587

Open RyanAD opened 4 months ago

RyanAD commented 4 months ago

Version hyper = 1.2.0 hyper-util = 0.1.3

Description

When using: hyper_util::server::conn::auto::Builder::new(..).serve_connection_with_upgrades the io stream is wrapped with Rewind which is private and therefore cannot be used to call Upgraded::downcast.

To reproduce the issue I'v modified the upgrades example here: https://github.com/RyanAD/hyper-broken-upgrade

The shortened version is that handing a connection with:

hyper_util::server::conn::auto::Builder::new(TokioExecutor::new())
                    .serve_connection_with_upgrades(io, service_fn(server_upgrade)).await;

...

// downcast to the underlying TcpStream
let parts = upgraded
    .downcast::<TokioIo<TcpStream>>()
    .map_err(|_| "server: Unable to downcast Upgraded")?;

let mut conn: TcpStream = parts.io.into_inner();

Will fail, because the stream is actually wrapped in Rewind which is not visible externally and can't be used to call downcast.

Without using hyper_util::server::conn::auto::Builder::new it works as expected. This also prevents downcasting Upgraded when using axum::serve, but that can be worked around by setting up the handling manually without using auto::Builder

seanmonstar commented 3 months ago

Yea good point. Before, we were able to work around this explicitly since both types were in the same library. Now that they are separate, it will be trickier to do so. 🤔

conradludgate commented 2 months ago

bikeshedding/stopgap: hyper_util::server::conn::auto::upgrade::downcast::<T>(upgraded) (that's a horrible path but whatever).