This is a minimum working example (MWE) of a WebSocket echo server in Rust using axum
and tokio
.
The HTTPS handshake happens on the same route (/
) as the WebSocket connection.
This MWE uses the following dependencies in Cargo.toml
:
[dependencies]
axum = {version = "0.7.9", features = ["ws"]}
tokio = {version = "1.41.1", features = ["full"]}
The following resides in src/main.rs
:
1 use axum::{
2 response::Response,
3 routing::get,
4 Router,
5 // Include the WebSocketUpgrade extractor:
6 extract::ws::{WebSocket, WebSocketUpgrade},
7 };
8 use tokio;
9
10 // When a request comes in with the "Upgrade: websocket" header,
11 // you'll have `Some(ws)`. For regular HTTP requests, it will
12 // be `None`:
13 async fn handler(ws: Option<WebSocketUpgrade>) -> Response {
14 if let Some(ws) = ws {
15 // Handle WebSocket connection
16 ws.on_upgrade(handle_socket)
17 } else {
18 // Handle HTTP request
19 Response::new("Hello HTTP!".into())
20 }
21 }
22
23 // Basic echo server example:
24 async fn handle_socket(mut socket: WebSocket) {
25 while let Some(msg) = socket.recv().await {
26 if let Ok(msg) = msg {
27 if let Err(_) = socket.send(msg).await {
28 break;
29 }
30 }
31 }
32 }
33
34 #[tokio::main]
35 async fn main() {
36 let app = Router::new()
37 // Pass the handler that includes the `WebSocketUpgrade` extractor to your route:
38 .route("/", get(handler));
39
40 let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await.unwrap();
41 axum::serve(listener, app).await.unwrap();
42 }
43