Expand description
ยงWsForge - High-Performance WebSocket Framework for Rust
WsForge is a complete, production-ready WebSocket framework that combines exceptional
performance with an intuitive, type-safe API. Built on tokio-tungstenite
, it provides
everything needed to build real-time applications, from simple echo servers to complex
multiplayer games and chat platforms.
ยงOverview
WsForge brings together the best practices from modern web frameworks like Axum and combines them with the performance of Rustโs async ecosystem. Whether youโre building a chat application, real-time dashboard, collaborative editor, or multiplayer game, WsForge provides the tools you need.
ยง๐ Key Features
- ๐ High Performance: Built on tokio-tungstenite with zero-copy optimizations
- ๐ง Type-Safe Extractors: Automatic extraction of JSON, State, Connection info
- ๐ฏ Flexible Handlers: Return String, Message, Result, JsonResponse, or ()
- ๐ก Broadcasting: Built-in broadcast, broadcast_except, and targeted messaging
- โก Concurrent: Lock-free connection management using DashMap
- ๐ Lifecycle Hooks: on_connect and on_disconnect callbacks
- ๐ Hybrid Server: Serve static files and WebSocket on the same port
- ๐ก๏ธ Type Safety: Compile-time guarantees prevent common errors
- ๐จ Developer Friendly: Intuitive API similar to popular Rust web frameworks
- ๐ฆ Batteries Included: Macros, examples, and documentation
ยงQuick Start
Add WsForge to your Cargo.toml
:
[dependencies]
wsforge = "0.1.0"
tokio = { version = "1.40", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
ยงEcho Server Example
Create a simple echo server in just a few lines:
use wsforge::prelude::*;
async fn echo(msg: Message) -> Result<Message> {
Ok(msg)
}
#[tokio::main]
async fn main() -> Result<()> {
let router = Router::new()
.default_handler(handler(echo));
println!("WebSocket server running on ws://127.0.0.1:8080");
router.listen("127.0.0.1:8080").await?;
Ok(())
}
ยงChat Server Example
Build a real-time chat server with broadcasting:
use wsforge::prelude::*;
use std::sync::Arc;
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize)]
struct ChatMessage {
username: String,
text: String,
}
async fn chat_handler(
Json(msg): Json<ChatMessage>,
conn: Connection,
State(manager): State<Arc<ConnectionManager>>,
) -> Result<()> {
println!("{}: {}", msg.username, msg.text);
// Broadcast to everyone except sender
let response = serde_json::to_string(&msg)?;
manager.broadcast_except(conn.id(), Message::text(response));
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());
})
.on_disconnect(|manager, conn_id| {
println!("โ {} left (Total: {})", conn_id, manager.count());
});
router.listen("127.0.0.1:8080").await?;
Ok(())
}
ยงWeb Application Example
Create a hybrid server that serves static files and handles WebSocket connections:
use wsforge::prelude::*;
use std::sync::Arc;
async fn ws_handler(
msg: Message,
State(manager): State<Arc<ConnectionManager>>,
) -> Result<()> {
manager.broadcast(msg);
Ok(())
}
#[tokio::main]
async fn main() -> Result<()> {
let router = Router::new()
.serve_static("public") // Serve HTML/CSS/JS from ./public
.default_handler(handler(ws_handler));
println!("Server running on http://127.0.0.1:8080");
router.listen("127.0.0.1:8080").await?;
Ok(())
}
ยง๐ Core Concepts
ยงHandlers
Handlers are async functions that process WebSocket messages. They can extract data using type-safe extractors and return various response types:
use wsforge::prelude::*;
use std::sync::Arc;
// Simple handler
async fn simple() -> Result<String> {
Ok("Hello!".to_string())
}
// Handler with extractors
async fn with_extractors(
msg: Message,
conn: Connection,
State(manager): State<Arc<ConnectionManager>>,
) -> Result<()> {
println!("Received from {}: {:?}", conn.id(), msg);
Ok(())
}
ยงExtractors
Extractors automatically parse and validate data from messages and context:
Extractor | Description |
---|---|
Message | Raw WebSocket message |
Json<T> | Deserialize JSON automatically |
Connection | Access to the active connection |
State<T> | Shared application state |
ConnectInfo | Connection metadata |
Data | Raw binary data |
ยงBroadcasting
Send messages to multiple connections efficiently:
use wsforge::prelude::*;
use std::sync::Arc;
async fn broadcast_example(
msg: Message,
conn: Connection,
State(manager): State<Arc<ConnectionManager>>,
) -> Result<()> {
// Broadcast to all
manager.broadcast(msg.clone());
// Broadcast except sender
manager.broadcast_except(conn.id(), msg.clone());
// Broadcast to specific connections
let targets = vec!["conn_1".to_string(), "conn_2".to_string()];
manager.broadcast_to(&targets, msg);
Ok(())
}
ยงState Management
Share data across all connections:
use wsforge::prelude::*;
use std::sync::Arc;
struct Database {
// Database connection pool
}
struct Config {
max_connections: usize,
}
async fn handler(
State(db): State<Arc<Database>>,
State(config): State<Arc<Config>>,
) -> Result<String> {
Ok(format!("Max connections: {}", config.max_connections))
}
#[tokio::main]
async fn main() -> Result<()> {
let router = Router::new()
.with_state(Arc::new(Database {}))
.with_state(Arc::new(Config { max_connections: 100 }))
.default_handler(handler(handler));
router.listen("127.0.0.1:8080").await?;
Ok(())
}
ยง๐ฎ Complete Examples
ยงReal-Time Game Server
use wsforge::prelude::*;
use std::sync::Arc;
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize)]
struct GameMove {
player_id: u64,
x: f32,
y: f32,
}
async fn game_handler(
Json(game_move): Json<GameMove>,
conn: Connection,
State(manager): State<Arc<ConnectionManager>>,
) -> Result<()> {
// Broadcast move to all other players
let json = serde_json::to_string(&game_move)?;
manager.broadcast_except(conn.id(), Message::text(json));
Ok(())
}
#[tokio::main]
async fn main() -> Result<()> {
let router = Router::new()
.default_handler(handler(game_handler))
.on_connect(|manager, conn_id| {
println!("๐ฎ Player {} joined", conn_id);
});
router.listen("0.0.0.0:8080").await?;
Ok(())
}
ยงMulti-Room Chat
use wsforge::prelude::*;
use std::sync::Arc;
use std::collections::HashMap;
use tokio::sync::RwLock;
use serde::{Deserialize, Serialize};
#[derive(Clone)]
struct RoomManager {
rooms: Arc<RwLock<HashMap<String, Vec<String>>>>,
}
#[derive(Deserialize)]
struct RoomMessage {
room: String,
text: String,
}
async fn room_handler(
Json(msg): Json<RoomMessage>,
conn: Connection,
State(room_mgr): State<Arc<RoomManager>>,
State(conn_mgr): State<Arc<ConnectionManager>>,
) -> Result<()> {
// Get room members and broadcast
let rooms = room_mgr.rooms.read().await;
if let Some(members) = rooms.get(&msg.room) {
let json = serde_json::to_string(&msg)?;
conn_mgr.broadcast_to(members, Message::text(json));
}
Ok(())
}
ยง๐ง Advanced Features
ยงCustom Middleware
use wsforge::prelude::*;
async fn auth_middleware(
msg: Message,
extensions: &Extensions,
) -> Result<()> {
// Verify authentication token
let token = msg.as_text().ok_or(Error::custom("Invalid token"))?;
// Store user info in extensions
extensions.insert("user_id", 123_u64);
Ok(())
}
ยงGraceful Shutdown
use wsforge::prelude::*;
use tokio::signal;
#[tokio::main]
async fn main() -> Result<()> {
let router = Router::new();
tokio::select! {
result = router.listen("127.0.0.1:8080") => {
if let Err(e) = result {
eprintln!("Server error: {}", e);
}
}
_ = signal::ctrl_c() => {
println!("Shutting down gracefully...");
}
}
Ok(())
}
ยง๐ Performance
WsForge is designed for high performance:
- Concurrent Connections: Handles thousands of connections efficiently
- Lock-Free: DashMap-based connection management eliminates lock contention
- Zero-Copy: Minimizes allocations and copies where possible
- Async Native: Built on tokio for maximum async performance
- Benchmarked: 47K+ requests/second for simple echo operations
ยง๐ก๏ธ Security
- Path Traversal Protection: Static file handler prevents directory escapes
- Type Safety: Rustโs type system prevents common errors
- Input Validation: JSON parsing with serde provides automatic validation
- Connection Limits: Easy to implement rate limiting and connection caps
ยง๐ Documentation
ยง๐ค Contributing
Contributions are welcome! Please see our Contributing Guide.
ยง๐ License
Licensed under the MIT License. See LICENSE for details.
ยง๐ Acknowledgments
- Built with tokio-tungstenite
- Inspired by Axum
- Thanks to the Rust community
ยง๐ Links
- Author: Aarambh Dev Hub
- YouTube: @AarambhDevHub
- Support: Issues
Modulesยง
- connection
- WebSocket connection management and message handling.
- error
- Error types and result handling for WsForge.
- extractor
- Type-safe data extraction from WebSocket messages and context.
- handler
- Handler traits and implementations for WebSocket message processing.
- message
- WebSocket message types and utilities.
- middleware
- Middleware system for request/response processing.
- prelude
- Prelude module for convenient imports.
- router
- Routing and server management for WebSocket connections with middleware support.
- state
- Shared application state management.
- static_
files - Static file serving for hybrid HTTP/WebSocket servers.
Macrosยง
- routes
macros
- Creates a new Router instance.
Structsยง
- AppState
- A type-safe container for shared application state.
- Connect
Info - Extractor for connection metadata.
- Connection
- Represents an active WebSocket connection.
- Data
- Extractor for raw binary data.
- Extension
- Extractor for custom extension data.
- Extensions
- Container for request-scoped extension data.
- Handler
Service - Service wrapper for handler functions.
- Json
- Extractor for JSON data from messages.
- Json
Response - JSON response wrapper.
- Logger
Middleware - Built-in logger middleware for logging WebSocket messages.
- Message
- A WebSocket message.
- Middleware
Chain - Middleware chain holds all middlewares and the final handler.
- Next
- Represents the next middleware or handler in the chain.
- Path
- Extractor for path parameters.
- Query
- Extractor for query parameters.
- Route
- Represents a single route with its path and middleware chain.
- Router
- The main router for WebSocket servers with middleware support.
- State
- Extractor for shared application state.
- Static
File Handler - Handler for serving static files from a directory.
Enumsยง
- Error
- The main error type for WsForge operations.
- Message
Type - Represents the type of a WebSocket message.
Traitsยง
- Handler
- Core trait for message handlers.
- Into
Response - Trait for converting handler return values into WebSocket messages.
- Middleware
- Middleware trait that all middleware must implement.
Functionsยง
- handler
- Converts an async function into a handler.
Type Aliasesยง
- Connection
Id - A unique identifier for a WebSocket connection.
- Result
- A type alias for
Result<T, Error>
.
Attribute Macrosยง
- websocket_
handler macros
- Transforms an async function into a WebSocket handler.
Derive Macrosยง
- WebSocket
Handler macros
- Derives the Handler trait for custom handler types.
- WebSocket
Message macros
- Derives message conversion methods for custom types.