Actix Websockets

Hi, I'm trying to learn how to use websockets so I can create a real-time messaging system. I looked over the documentation for websockets on actix but I'm still a little confused on how to operate with it.

This is the referred to code which is a websocket echo server:

use actix::{Actor, StreamHandler};
use actix_web::{web, App, Error, HttpRequest, HttpResponse, HttpServer};
use actix_web_actors::ws;

/// Define HTTP actor
struct MyWs;

impl Actor for MyWs {
    type Context = ws::WebsocketContext<Self>;
}

/// Handler for ws::Message message
impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for MyWs {
    fn handle(
        &mut self,
        msg: Result<ws::Message, ws::ProtocolError>,
        ctx: &mut Self::Context,
    ) {
        match msg {
            Ok(ws::Message::Ping(msg)) => ctx.pong(&msg),
            Ok(ws::Message::Text(text)) => ctx.text(text),
            Ok(ws::Message::Binary(bin)) => ctx.binary(bin),
            _ => (),
        }
    }
}

async fn index(req: HttpRequest, stream: web::Payload) -> Result<HttpResponse, Error> {
    let resp = ws::start(MyWs {}, &req, stream);
    println!("{:?}", resp);
    resp
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| App::new().route("/ws/", web::get().to(index)))
        .bind("127.0.0.1:8080")?
        .run()
        .await
}

My question is how do I actually send a message for it to then be echoed back. I'm confused on how to trigger this from the clientside because obviously with only this I'm led to a 404/400 error since an html page isn't found at localhost:8080? I know some clientside html and javascript is needed, but I'd appreciate an example: do I need to send some kind of post or get request to the websocket server?

Thanks in advance!

I would just use node locally to test experiment to start. This LINK explains how to connect with JavaScript. I think it should work just fine using node as a client. Then if you want to move it to a browser you can just copy the code to and html page.

Thanks Drew this looks like what I was looking for!

I used to do the node.js web socket client thing for testing my web socket servers. It's pretty quick and simple to get going.

But then I though, "Nah, let's oxidize it all and make a command line web socket client in Rust"

Which I did with the tokio-tungstenite web socket crate:https://docs.rs/tokio-tungstenite/0.11.0/tokio_tungstenite/

Which has support for both web socket servers and clients.

I can make a minimal web socket command line client example if you are interested. What I have here is a bit long winded what with also using JSON web tokens and supporting TLS connections and other junk.

Hi ZiCog, thank you for your consideration and suggestion and while I'd like to take a look for curiosity's sake, practically speaking I'm completely fine with the client being a different language as long as the server itself is in Rust for performance reasons. I'm quite content with a javascript client.

Perhaps that is wise. Especially if you are familiar with the node.js world.

It was a bit of an exercise for me just to see how it would go in Rust. I was surprised that it's not such a lot more effort, or lines of code, at the end of the day.

To @ZiCog’s point though, if you are planning on having a client that runs as an executable on the machine, using rust might let you share code in addition to type safety benefits. It sort of depends on the functionality whether there would be any significant code sharing. If you want the ability to connect via browser as well, then that’s not as obvious since you would need to get into wasm and the benefits might not actually come to fruition since you might need significant js anyway.

To be clear, all my browser side stuff is still Javascript. I don't see that changing any time soon. As far as I know one cannot even make a web socket connection from WASM, at least not without some complicated WASM/JS glue.

I just wanted a CLI tool to exercise my web socket servers so anything would do. Oxidizing it was just an experiment that happily turned out well enough.

1 Like