Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running websocket and http server on the same port (Rust, hyper)

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.

like image 785
cruppstahl Avatar asked Aug 21 '17 22:08

cruppstahl


People also ask

Can HTTP and WebSocket use same port?

Sharing port is possible since You can have both the HTTP server and the Websocket server in one process.

Can I use WebSockets and HTTP?

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.

Should I use WebSocket or HTTP?

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.

Is WebSocket faster than HTTP?

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.


1 Answers

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();
like image 79
Alex jg Avatar answered Sep 19 '22 18:09

Alex jg