rainier-websocket 1.0.1

WebSockets for Rainier: the handler contract, the socket handle, and the route table.
Documentation
rainier-websocket-1.0.1 has been yanked.

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:

Broadcasting This
Who holds the socket a separate process (soketi, Pusher) your process
Direction out only both ways
Scales across instances yes, through Redis one instance per socket
Client Laravel Echo anything 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.