Welcome to WsForge! This guide will help you build your first WebSocket server in just a few minutes.
WsForge is a high-performance WebSocket framework for Rust that combines the power of tokio-tungstenite with an intuitive, type-safe API inspired by modern web frameworks like Axum. It's designed to make building real-time applications easy, fast, and enjoyable.
Key Features:
- 🚀 High performance with async/await
- 🔧 Type-safe extractors (JSON, State, Connection)
- 📡 Built-in broadcasting support
- 🌐 Hybrid HTTP/WebSocket server
- 🛡️ Compile-time safety guarantees
Before you begin, make sure you have:
- Rust 1.70 or later - Install via rustup
- Basic knowledge of async/await in Rust (helpful but not required)
- A code editor (VS Code with rust-analyzer recommended)
Check your Rust version:
rustc --versionOpen your terminal and create a new Rust project:
cargo new my-websocket-server
cd my-websocket-serverOpen Cargo.toml and add WsForge:
[package]
name = "my-websocket-server"
version = "0.1.0"
edition = "2021"
[dependencies]
wsforge = "0.1.0"
tokio = { version = "1.40", features = ["full"] }Replace the contents of src/main.rs with:
use wsforge::prelude::*;
// Handler function that echoes messages back
async fn echo_handler(msg: Message) -> Result<Message> {
println!("📨 Received: {:?}", msg.as_text());
Ok(msg) // Echo the message back
}
#[tokio::main]
async fn main() -> Result<()> {
// Create a router with the echo handler
let router = Router::new()
.default_handler(handler(echo_handler));
println!("🚀 WebSocket server running on ws://127.0.0.1:8080");
println!("📡 Press Ctrl+C to stop");
// Start listening for connections
router.listen("127.0.0.1:8080").await?;
Ok(())
}Start the server:
cargo runYou should see:
🚀 WebSocket server running on ws://127.0.0.1:8080
📡 Press Ctrl+C to stopOpen your browser's developer console (F12) and paste:
const ws = new WebSocket('ws://localhost:8080');
ws.onopen = () => {
console.log('✅ Connected!');
ws.send('Hello, WsForge!');
};
ws.onmessage = (event) => {
console.log('📨 Received:', event.data);
};
ws.onerror = (error) => {
console.error('❌ Error:', error);
};Install websocat:
# macOS
brew install websocat
# Linux
cargo install websocat
# Windows (via cargo)
cargo install websocatConnect and send messages:
websocat ws://127.0.0.1:8080Type any message and press Enter. You should see it echoed back!
Visit websocket.org/echo.html and connect to ws://localhost:8080.
Let's break down what we just built:
use wsforge::prelude::*;Imports all commonly used WsForge types.
async fn echo_handler(msg: Message) -> Result<Message> {
Ok(msg)
}A handler function that receives a Message and returns it unchanged. Handlers can extract various types and return different response types.
let router = Router::new()
.default_handler(handler(echo_handler));Creates a Router that directs all messages to our echo handler.
router.listen("127.0.0.1:8080").await?;Starts the server on port 8080.
Let's enhance the server with connection tracking:
use wsforge::prelude::*;
async fn echo_handler(msg: Message) -> Result<Message> {
Ok(msg)
}
#[tokio::main]
async fn main() -> Result<()> {
let router = Router::new()
.default_handler(handler(echo_handler))
.on_connect(|manager, conn_id| {
println!("✅ Client {} connected (Total: {})",
conn_id, manager.count());
})
.on_disconnect(|manager, conn_id| {
println!("❌ Client {} disconnected (Remaining: {})",
conn_id, manager.count());
});
println!("🚀 WebSocket server running on ws://127.0.0.1:8080");
router.listen("127.0.0.1:8080").await?;
Ok(())
}Now when clients connect or disconnect, you'll see logs!
Let's create something more interactive:
use wsforge::prelude::*;
use std::sync::Arc;
async fn chat_handler(
msg: Message,
conn: Connection,
State(manager): State<Arc<ConnectionManager>>,
) -> Result<()> {
println!("💬 {} says: {:?}", conn.id(), msg.as_text());
// Broadcast to everyone except the sender
manager.broadcast_except(conn.id(), msg);
Ok(())
}
#[tokio::main]
async fn main() -> Result<()> {
let router = Router::new()
.default_handler(handler(chat_handler))
.on_connect(|manager, conn_id| {
println!("✅ {} joined (Total: {})", conn_id, manager.count());
// Send welcome message to the new user
if let Some(conn) = manager.get(&conn_id) {
let _ = conn.send_text("Welcome to the chat!");
}
});
println!("🚀 Chat server running on ws://127.0.0.1:8080");
router.listen("127.0.0.1:8080").await?;
Ok(())
}What's different?
- Handler extracts
ConnectionandState<Arc<ConnectionManager>> - Uses
broadcast_except()to send messages to all other clients - Sends a welcome message to new users
use wsforge::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Deserialize)]
struct Request {
action: String,
data: String,
}
#[derive(Serialize)]
struct Response {
status: String,
result: String,
}
async fn json_handler(Json(req): Json<Request>) -> Result<JsonResponse<Response>> {
println!("Action: {}", req.action);
Ok(JsonResponse(Response {
status: "success".to_string(),
result: format!("Processed: {}", req.data),
}))
}async fn echo(msg: Message) -> Result<Message> {
Ok(msg)
}
async fn uppercase(msg: Message) -> Result<String> {
let text = msg.as_text().unwrap_or("");
Ok(text.to_uppercase())
}
#[tokio::main]
async fn main() -> Result<()> {
let router = Router::new()
.route("/echo", handler(echo))
.route("/upper", handler(uppercase))
.default_handler(handler(|_: Message| async {
Ok("Unknown route".to_string())
}));
router.listen("127.0.0.1:8080").await?;
Ok(())
}Send messages like /echo hello or /upper hello to use different routes!
Error: Address already in use
Solution: Change the port or kill the process using port 8080:
# macOS/Linux
lsof -ti:8080 | xargs kill
# Windows
netstat -ano | findstr :8080
taskkill /PID <PID> /FError: Connection refused
Solution:
- Ensure the server is running
- Check firewall settings
- Verify you're using
ws://notwss://for local testing
Error: cannot find type Message in this scope
Solution: Make sure you have use wsforge::prelude::*; at the top of your file.
Now that you have a working WebSocket server, explore more:
- Handlers Guide - Learn about different handler types
- Extractors - Deep dive into type extractors
- Broadcasting - Advanced message distribution
- State Management - Share data across connections
- Examples - Complete example applications
- GitHub Repository: github.com/aarambhdevhub/wsforge
- API Documentation: Run
cargo doc --openin your project - YouTube Tutorials: @AarambhDevHub
- Example Projects: Check the
examples/directory in the repository
- Issues: GitHub Issues
- Questions: GitHub Discussions
- Documentation: docs.rs/wsforge
Happy coding with WsForge! 🚀