Skip to main content

Crate rainier_websocket

Crate rainier_websocket 

Source
Expand description

WebSockets — a connection that stays open, served alongside HTTP.

ⓘ
pub struct Chat {
    rooms: Arc<Rooms>,
}

#[async_trait]
impl WebSocketHandler for Chat {
    async fn on_connect(&self, socket: &Socket) -> Result<()> {
        let room = socket.param("room").unwrap_or("lobby").to_string();
        self.rooms.join(&room, socket.clone());
        Ok(())
    }

    async fn on_message(&self, socket: &Socket, message: Message) -> Result<()> {
        let room = socket.param("room").unwrap_or("lobby");
        self.rooms.send_except(room, socket.id(), message);
        Ok(())
    }

    async fn on_close(&self, socket: &Socket) {
        self.rooms.leave_all(socket.id());
    }
}

// routes/ws.rs
WebSocketRoutes::new().add("/ws/rooms/{room}", Chat { rooms })

§It shares the HTTP server

A WebSocket connection starts as an HTTP request — a GET carrying Upgrade: websocket. So there is no second listener, no second port and no second runtime: the same accept loop takes both, and a socket is a connection that answered 101 instead of 200 and then kept going.

Concurrency falls out of that rather than being arranged. Every connection is already its own task, so a thousand idle sockets are a thousand parked futures and cost nothing while they wait.

GET /ws/rooms/7  Upgrade: websocket
       │
       ├── no handler at that path ──▶ 404, like any other route
       ├── handler says no ──────────▶ 403, before the handshake
       └── 101 Switching Protocols ──▶ on_connect → on_message* → on_close

§This crate is the contract, not the transport

Nothing here speaks TCP or knows what a frame looks like on the wire — rainier-server does the upgrade and the framing. That split is what lets a handler be tested by calling it: Socket is a channel, so on_message can be driven with no network at all.

§Broadcasting, and when to use which

rainier-broadcast also pushes to browsers, and the two are not competitors:

BroadcastingThis
Who holds the socketa separate process (soketi, Pusher)your process
Directionout onlyboth ways
Scales across instancesyes, through Redisone instance per socket
Clienta Pusher-protocol clientanything that speaks WebSocket

Broadcast when the browser only needs to hear. Use a socket when it needs to talk back, or when you would rather not run a second process. Note the third row before choosing: a Rooms registry lives in one process’s memory, so two instances behind a load balancer have two sets of rooms.

Re-exports§

pub use handler::Matched;
pub use handler::Rooms;
pub use handler::WebSocketHandler;
pub use handler::WebSocketRoutes;
pub use message::Message;
pub use socket::instance_id;
pub use socket::socket_from_identity;
pub use socket::Outbound;
pub use socket::Socket;
pub use socket::SocketId;

Modules§

handler
What an application writes — WebSocketHandler and the route table.
message
What travels over a socket — Message.
socket
The handle a handler holds — Socket.