Skip to content

Allow constructing an OnUpgrade outside of hyper #4034

@bjorn3

Description

@bjorn3

Is your feature request related to a problem? Please describe.
I would like to test a web server that uses axum without listening on any tcp port. For most requests this is fairly easy by constructing an http::Request and using axum::Router::oneshot. However for websockets this doesn't work. Axum needs the http::Request to contain a hyper::upgrade::OnUpgrade extension. There doesn't seem to be a way to construct one without doing an actual http request over the network using hyper.

Describe the solution you'd like
Make hyper::upgrade::pending, hyper::upgrade::Upgrade::new and hyper::upgrade::Pending::fulfill public.

Describe alternatives you've considered
Binding to a tcp port would be possible, but would add complexity to the tests to handle concurrent tests and to run the server in a background task that needs to be killed again at the end of the test.

Additional context
Something like the following should work once those methods are made public:

let (pending, on_upgrade) = hyper::upgrade::pending();

let (left, right) = tokio::io::duplex(1024);
pending.fulfill(hyper::upgrade::Upgraded::new(
    hyper_util::rt::tokio::TokioIo::new(left),
    Bytes::new(),
));

let response = router
    .oneshot(
        Request::builder()
            .method(Method::GET)
            .uri(path)
            .header(
                http::header::AUTHORIZATION,
                format!("Bearer {}", self.token),
            )
            .header(http::header::UPGRADE, "websocket")
            .header(http::header::CONNECTION, "Upgrade")
            .header(http::header::SEC_WEBSOCKET_KEY, "dGhlIHNhbXBsZSBub25jZQ==")
            .header(http::header::SEC_WEBSOCKET_VERSION, "13")
            .extension(on_upgrade)
            .body(Body::empty())
            .unwrap(),
    )
    .await
    .unwrap();

let ws = tokio_tungstenite::WebSocketStream::from_raw_socket(
    right,
    tokio_tungstenite::tungstenite::protocol::Role::Client,
    None,
)
.await;

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-featureCategory: feature. This is adding a new feature.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions