pub struct Router { /* private fields */ }Expand description
The main router for WebSocket servers.
Router is the central component that manages routing, state, connections,
and server lifecycle. It uses a builder pattern for configuration and
supports both WebSocket and HTTP static file serving on the same port.
§Thread Safety
Router is thread-safe and can be cloned cheaply (uses Arc internally).
All connections share the same router instance.
§Lifecycle
- Create router with
Router::new() - Configure routes, state, handlers, callbacks
- Call
listen()to start the server - Router handles incoming connections automatically
§Examples
§Basic Setup
use wsforge::prelude::*;
async fn handler(msg: Message) -> Result<String> {
Ok("received".to_string())
}
let router = Router::new()
.default_handler(handler(handler));
router.listen("0.0.0.0:8080").await?;§With Shared State
use wsforge::prelude::*;
use std::sync::Arc;
struct AppConfig {
max_connections: usize,
}
async fn handler(State(config): State<Arc<AppConfig>>) -> Result<String> {
Ok(format!("Max connections: {}", config.max_connections))
}
let config = Arc::new(AppConfig { max_connections: 100 });
let router = Router::new()
.with_state(config)
.default_handler(handler(handler));
router.listen("127.0.0.1:8080").await?;Implementations§
Source§impl Router
impl Router
Sourcepub fn new() -> Self
pub fn new() -> Self
Creates a new empty router.
The router starts with no routes, no state, and no handlers. Use the builder methods to configure it.
§Examples
use wsforge::prelude::*;
let router = Router::new();Sourcepub fn route(self, path: impl Into<String>, handler: Arc<dyn Handler>) -> Self
pub fn route(self, path: impl Into<String>, handler: Arc<dyn Handler>) -> Self
Registers a handler for a specific route.
Routes are matched against the beginning of incoming messages.
For example, a message like /chat hello would match route /chat.
§Arguments
path- The route path (e.g., “/chat”, “/api/users”)handler- The handler function wrapped withhandler()
§Examples
use wsforge::prelude::*;
async fn chat_handler(msg: Message) -> Result<String> {
Ok("chat response".to_string())
}
async fn api_handler(msg: Message) -> Result<String> {
Ok("api response".to_string())
}
let router = Router::new()
.route("/chat", handler(chat_handler))
.route("/api", handler(api_handler));Sourcepub fn with_state<T: Send + Sync + 'static>(self, data: Arc<T>) -> Self
pub fn with_state<T: Send + Sync + 'static>(self, data: Arc<T>) -> Self
Adds shared state to the router.
State is shared across all connections and can be extracted in handlers
using the [State] extractor. Any type that is Send + Sync + 'static
can be used as state.
§Type Safety
Multiple different types can be added as state. Each type is stored separately and retrieved by type.
§Arguments
data- The state data to share
§Examples
§Single State
use wsforge::prelude::*;
use std::sync::Arc;
struct Database {
// database fields
}
async fn handler(State(db): State<Arc<Database>>) -> Result<String> {
Ok("query result".to_string())
}
let db = Arc::new(Database {});
let router = Router::new()
.with_state(db)
.default_handler(handler(handler));§Multiple States
use wsforge::prelude::*;
use std::sync::Arc;
struct Config {
port: u16,
}
struct Database {
// database fields
}
let router = Router::new()
.with_state(Arc::new(Config { port: 8080 }))
.with_state(Arc::new(Database {}));Sourcepub fn on_connect<F>(self, f: F) -> Self
pub fn on_connect<F>(self, f: F) -> Self
Sets a callback to be called when a new connection is established.
The callback receives a reference to the connection manager and the connection ID. This is useful for logging, sending welcome messages, or updating user lists.
§Arguments
f- Callback function with signatureFn(&Arc<ConnectionManager>, ConnectionId)
§Examples
§Simple Logging
use wsforge::prelude::*;
let router = Router::new()
.on_connect(|manager, conn_id| {
println!("New connection: {} (Total: {})", conn_id, manager.count());
});§Send Welcome Message
use wsforge::prelude::*;
let router = Router::new()
.on_connect(|manager, conn_id| {
if let Some(conn) = manager.get(&conn_id) {
let _ = conn.send_text("Welcome to the server!");
}
});§Broadcast Join Notification
use wsforge::prelude::*;
let router = Router::new()
.on_connect(|manager, conn_id| {
let msg = format!("User {} joined", conn_id);
manager.broadcast(Message::text(msg));
});Sourcepub fn on_disconnect<F>(self, f: F) -> Self
pub fn on_disconnect<F>(self, f: F) -> Self
Sets a callback to be called when a connection is closed.
The callback receives a reference to the connection manager and the connection ID. Note that the connection is already removed from the manager when this is called.
§Arguments
f- Callback function with signatureFn(&Arc<ConnectionManager>, ConnectionId)
§Examples
§Logging Disconnections
use wsforge::prelude::*;
let router = Router::new()
.on_disconnect(|manager, conn_id| {
println!("Connection {} closed (Remaining: {})", conn_id, manager.count());
});§Broadcast Leave Notification
use wsforge::prelude::*;
let router = Router::new()
.on_disconnect(|manager, conn_id| {
let msg = format!("User {} left", conn_id);
manager.broadcast(Message::text(msg));
});Sourcepub fn default_handler(self, handler: Arc<dyn Handler>) -> Self
pub fn default_handler(self, handler: Arc<dyn Handler>) -> Self
Sets the default handler for messages that don’t match any route.
This handler is called when no route matches the incoming message. Use this for catch-all behavior or when you don’t need routing.
§Arguments
handler- The default handler wrapped withhandler()
§Examples
§Echo Server
use wsforge::prelude::*;
async fn echo(msg: Message) -> Result<Message> {
Ok(msg)
}
let router = Router::new()
.default_handler(handler(echo));§Error Handler
use wsforge::prelude::*;
async fn not_found() -> Result<String> {
Ok("Unknown command".to_string())
}
let router = Router::new()
.route("/known", handler(not_found))
.default_handler(handler(not_found));Sourcepub fn serve_static(self, path: impl Into<PathBuf>) -> Self
pub fn serve_static(self, path: impl Into<PathBuf>) -> Self
Enables static file serving from a directory.
When enabled, the router will serve static files (HTML, CSS, JavaScript, images) from the specified directory for HTTP requests, while still handling WebSocket connections on the same port.
§Path Resolution
- Requests to
/serveindex.htmlfrom the directory - Other requests map directly to files (e.g.,
/style.css→directory/style.css) - MIME types are automatically detected
§Security
Path traversal attempts (e.g., ../../etc/passwd) are automatically blocked.
§Arguments
path- Path to the directory containing static files
§Examples
§Serve Static Files
use wsforge::prelude::*;
async fn ws_handler(msg: Message) -> Result<Message> {
Ok(msg)
}
let router = Router::new()
.serve_static("public") // Serve files from ./public
.default_handler(handler(ws_handler));
// Now you can access:
// http://localhost:8080/ -> public/index.html
// http://localhost:8080/app.js -> public/app.js
// ws://localhost:8080 -> WebSocket handler§Web Chat Application
use wsforge::prelude::*;
async fn chat_handler(msg: Message, State(manager): State<Arc<ConnectionManager>>) -> Result<()> {
manager.broadcast(msg);
Ok(())
}
let router = Router::new()
.serve_static("chat-ui") // HTML/CSS/JS for chat interface
.default_handler(handler(chat_handler));Sourcepub fn connection_manager(&self) -> Arc<ConnectionManager>
pub fn connection_manager(&self) -> Arc<ConnectionManager>
Returns a reference to the connection manager.
The connection manager is automatically created with the router. Use this to get access to it for storing in state or elsewhere.
§Examples
use wsforge::prelude::*;
let router = Router::new();
let manager = router.connection_manager();
// Now you can use the manager
println!("Active connections: {}", manager.count());Sourcepub async fn listen(self, addr: impl AsRef<str>) -> Result<()>
pub async fn listen(self, addr: impl AsRef<str>) -> Result<()>
Starts the WebSocket server and listens for connections.
This method consumes the router and starts the server loop. It will run indefinitely until the process is terminated or an error occurs.
§Arguments
addr- The address to bind to (e.g., “127.0.0.1:8080”, “0.0.0.0:3000”)
§Errors
Returns an error if:
- The address format is invalid
- The port is already in use
- Permission is denied (e.g., ports < 1024 on Unix)
§Examples
§Basic Usage
use wsforge::prelude::*;
let router = Router::new();
router.listen("127.0.0.1:8080").await?;§All Interfaces
use wsforge::prelude::*;
let router = Router::new();
router.listen("0.0.0.0:8080").await?; // Accept connections from anywhere§With Error Handling
use wsforge::prelude::*;
let router = Router::new();
match router.listen("127.0.0.1:8080").await {
Ok(_) => println!("Server stopped"),
Err(e) => eprintln!("Server error: {}", e),
}