I want to write a webserver using Rust, Hyper and websocket-rs. The webserver must be able to handle http requests AND websocket requests on the same port. I used the official sample (async-server.rs
: https://github.com/cyderize/rust-websocket/blob/master/examples/async-server.rs) and tried to modify it. My idea was to change the error handling. If the client's request is a simple http request then do not return an error, but spawn a future which handles the request instead.
Based on another SO question (How do I handle an error when using rust-websocket so that only that connection fails and not the entire program?) I changed the error handling from the sample.
This is the old code:
.map_err(|InvalidConnection {error, ..}| {
println!("Error:{:?}",error);
return error;
})
Here is my new code:
.map(Some).or_else(|_| -> Result<_, ()> {
// SPAWN THE FUTURE
Ok(None)
})
This is where I am stuck. The sample code calls a function spawn_future
, which expects a parameter (upgrade.reject()
) which is not available in my code since I do not have access to an upgrade
structure. I tried a few other things (i.e. calling handle.spawn_fn
) but the compiler never liked what I did. (I could paste some of the compiler errors, but I do not think that they would improve the quality of my post.)
Here is my question: What is the recommended way to write an asynchronous server which can handle http requests AND websocket requests on the same port? If my approach is correct: can you please help me to fill the SPAWN THE FUTURE
line?
Additional context (if you haven't noticed yet): I am a total Rust beginner.
Sharing port is possible since You can have both the HTTP server and the Websocket server in one process.
ANY WebSocket implementation MUST use HTTP (and all semantics therein, including authentication, redirection, etc) for the initial handshake. It is mandated by the WebSocket protocol specification, RFC 6455. So, a dedicated WebSockets server must be able to handle HTTP requests during the handshake phase, at least.
WebSockets allow for a higher amount of efficiency compared to REST because they do not require the HTTP request/response overhead for each message sent and received. When a client wants ongoing updates about the state of the resource, WebSockets are generally a good fit.
All the frequently updated applications used WebSocket because it is faster than HTTP Connection. When we do not want to retain a connection for a particular amount of time or reuse the connection for transmitting data; An HTTP connection is slower than WebSockets.
There seems to be some docs on this in the rust-websocket documentation here
Pasting from the docs:
use hyper::server::{Server, Request, Response};
use websocket::Message;
use websocket::sync::server::upgrade::IntoWs;
use websocket::sync::server::upgrade::HyperRequest;
Server::http("0.0.0.0:80").unwrap().handle(move |req: Request, res: Response| {
match HyperRequest(req).into_ws() {
Ok(upgrade) => {
// `accept` sends a successful handshake, no need to worry about res
let mut client = match upgrade.accept() {
Ok(c) => c,
Err(_) => panic!(),
};
client.send_message(&Message::text("its free real estate"));
},
Err((request, err)) => {
// continue using the request as normal, "echo uri"
res.send(b"Try connecting over ws instead.").unwrap();
},
};
})
.unwrap();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With