WebSocket Proxy
WsProxy listens for incoming HTTP/1.1 connections, validates that each connection is a WebSocket upgrade, forwards the upgrade handshake to a backend, and then tunnels all subsequent WebSocket frames bidirectionally.
Basic usage
use rust_web_server::ws_proxy::WsProxy;
// Proxy all WebSocket connections on port 8080 to two chat backendsWsProxy::new(["chat-backend:9000", "chat-backend:9001"]) .connect_timeout_ms(3_000) .bind("0.0.0.0:8080") .unwrap();.bind() blocks the calling thread indefinitely. Run it in a dedicated thread or process.
Connection flow
For each incoming TCP connection, WsProxy follows this sequence:
- Read the initial HTTP request (up to 8 192 bytes).
- Validate that the request contains a WebSocket
Upgradeheader. Non-upgrade requests receive400 Bad Requestand are closed. - Connect to the selected backend using the configured connect timeout.
- Forward the HTTP upgrade request to the backend (rewriting the
Hostheader). - Verify the backend responds with
HTTP/1.1 101 Switching Protocols. - Send
101 Switching Protocolsto the client, completing the client-side handshake. - Relay all subsequent bytes bidirectionally in two threads (one per direction).
The relay threads use std::io::copy and shut down their half of the connection when the remote side closes.
Round-robin backend selection
An AtomicUsize counter cycles through backends evenly across connections with no locking:
WsProxy::new([ "ws-backend-1:9000", "ws-backend-2:9000", "ws-backend-3:9000",])Timeout configuration
WsProxy::new(backends) .connect_timeout_ms(5_000) // TCP connect to backend (default: 5 000 ms) .read_timeout_ms(30_000) // idle read timeout on client connections (default: 30 000 ms)The read timeout applies to the initial HTTP upgrade read from the client. After the tunnel is established, there is no application-level read timeout — the connection stays open until either side closes it.
Config-file usage
Activate WsProxy from rws.config.toml with a [[ws_proxy]] section:
[[ws_proxy]]bind = "0.0.0.0:8080"backends = ["ws-backend-1:9000", "ws-backend-2:9000"]connect_timeout_ms = 3000Multiple [[ws_proxy]] sections can run independently on separate ports.
TLS WebSocket (wss://)
WsProxy accepts plain HTTP/1.1 only. To proxy wss:// clients, place an rws instance configured with TLS (--tls-cert-file) in front and point its downstream at this proxy:
wss:// client ──► rws (TLS termination, port 443) ──► WsProxy (plain, port 8080) ──► backendUse cases
- Chat servers and real-time messaging (Socket.IO, Phoenix Channels, Action Cable)
- Live data feeds and dashboards
- Multiplayer game backends
- Collaborative editing services
- Any service that upgrades HTTP to the WebSocket protocol