-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
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;