Crate wsforge_core

Crate wsforge_core 

Source
Expand description

Β§WsForge Core - High-Performance WebSocket Framework

wsforge-core is the foundational library for the WsForge WebSocket framework. It provides type-safe, ergonomic abstractions for building real-time WebSocket applications with exceptional performance and developer experience.

Β§Overview

WsForge Core combines the power of tokio-tungstenite with a flexible, type-safe API inspired by modern web frameworks like Axum. It’s designed for building production-ready WebSocket servers that are both fast and maintainable.

Β§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 various types - String, Message, Result, JsonResponse
  • πŸ“‘ Broadcasting: Built-in broadcast, broadcast_except, and targeted messaging
  • ⚑ Concurrent: Lock-free connection management with DashMap
  • πŸ”„ Lifecycle Hooks: on_connect and on_disconnect callbacks
  • 🌐 Hybrid Server: Serve static files and WebSocket on same port
  • πŸ›‘οΈ Type Safety: Compile-time guarantees for correctness

Β§Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        Application                            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  Handlers  β”‚  β”‚  Router  β”‚  β”‚  State & Extractors   β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      WsForge Core                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚  Connection  β”‚  β”‚     Message     β”‚  β”‚   Static Files  β”‚ β”‚
β”‚  β”‚   Manager    β”‚  β”‚     Router      β”‚  β”‚     Handler     β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    tokio-tungstenite                          β”‚
β”‚                  (WebSocket Protocol)                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Β§Module Structure

  • connection: WebSocket connection management and lifecycle
  • message: Message types and parsing utilities
  • [handler]: Handler trait and response types
  • extractor: Type-safe data extraction from messages
  • router: Routing and server management
  • state: Shared application state container
  • error: Error types and result handling
  • static_files: Static file serving for hybrid servers

Β§Quick Start Examples

Β§Echo Server

The simplest possible WebSocket server:

use wsforge_core::prelude::*;

async fn echo(msg: Message) -> Result<Message> {
    Ok(msg)
}

#[tokio::main]
async fn main() -> Result<()> {
    let router = Router::new()
        .default_handler(handler(echo));

    router.listen("127.0.0.1:8080").await?;
    Ok(())
}

Β§Chat Server with Broadcasting

A real-time chat application:

use wsforge_core::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!("βœ… {} connected (Total: {})", conn_id, manager.count());
        })
        .on_disconnect(|manager, conn_id| {
            println!("❌ {} disconnected", conn_id);
        });

    router.listen("127.0.0.1:8080").await?;
    Ok(())
}

Β§Web Application with Static Files

Hybrid HTTP/WebSocket server:

use wsforge_core::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
        .default_handler(handler(ws_handler));

    // Handles both:
    // http://localhost:8080/        -> public/index.html
    // ws://localhost:8080           -> WebSocket handler

    router.listen("0.0.0.0:8080").await?;
    Ok(())
}

Β§Handler Patterns

Β§Simple Handler

use wsforge_core::prelude::*;

async fn simple_handler() -> Result<String> {
    Ok("Hello, WebSocket!".to_string())
}

Β§With JSON Extraction

use wsforge_core::prelude::*;
use serde::Deserialize;

#[derive(Deserialize)]
struct Request {
    action: String,
    data: String,
}

async fn json_handler(Json(req): Json<Request>) -> Result<String> {
    Ok(format!("Action: {}, Data: {}", req.action, req.data))
}

Β§With State and Connection

use wsforge_core::prelude::*;
use std::sync::Arc;

async fn stateful_handler(
    msg: Message,
    conn: Connection,
    State(manager): State<Arc<ConnectionManager>>,
) -> Result<String> {
    Ok(format!(
        "Connection {} | {} total connections",
        conn.id(),
        manager.count()
    ))
}

Β§Extractors

WsForge provides powerful type-safe extractors:

ExtractorDescriptionExample
MessageRaw messagemsg: Message
Json<T>JSON deserializationJson(data): Json<MyStruct>
ConnectionActive connectionconn: Connection
State<T>Shared stateState(db): State<Arc<Database>>
ConnectInfoConnection metadataConnectInfo(info)
DataRaw bytesData(bytes): Data

Β§Response Types

Handlers can return various types:

use wsforge_core::prelude::*;

// No response
async fn handler1() -> Result<()> {
    Ok(())
}

// Text response
async fn handler2() -> Result<String> {
    Ok("response".to_string())
}

// Raw message
async fn handler3() -> Result<Message> {
    Ok(Message::text("response"))
}

// Binary response
async fn handler4() -> Result<Vec<u8>> {
    Ok(vec!)[1][2][3][4]
}

// JSON response
async fn handler5() -> Result<JsonResponse<serde_json::Value>> {
    Ok(JsonResponse(serde_json::json!({"status": "ok"})))
}

Β§Broadcasting Patterns

Β§Broadcast to All

use wsforge_core::prelude::*;
use std::sync::Arc;

async fn broadcast_all(
    msg: Message,
    State(manager): State<Arc<ConnectionManager>>,
) -> Result<()> {
    manager.broadcast(msg);
    Ok(())
}

Β§Broadcast Except Sender

use wsforge_core::prelude::*;
use std::sync::Arc;

async fn broadcast_others(
    msg: Message,
    conn: Connection,
    State(manager): State<Arc<ConnectionManager>>,
) -> Result<()> {
    manager.broadcast_except(conn.id(), msg);
    Ok(())
}

Β§Targeted Broadcasting

use wsforge_core::prelude::*;
use std::sync::Arc;

async fn broadcast_to_room(
    msg: Message,
    State(manager): State<Arc<ConnectionManager>>,
) -> Result<()> {
    let room_members = vec!["conn_1".to_string(), "conn_2".to_string()];
    manager.broadcast_to(&room_members, msg);
    Ok(())
}

Β§Error Handling

WsForge provides comprehensive error handling:

use wsforge_core::prelude::*;

async fn safe_handler(msg: Message) -> Result<String> {
    // Parse JSON
    let data: serde_json::Value = msg.json()?;

    // Validate
    if data.is_null() {
        return Err(Error::custom("Data cannot be null"));
    }

    // Process and return
    Ok("processed".to_string())
}

Β§Performance Characteristics

  • Connection Management: O(1) lock-free operations via DashMap
  • Message Routing: O(1) handler lookup
  • Broadcasting: O(n) where n is the number of connections
  • Memory: Zero-copy message handling where possible
  • Concurrency: Full async/await with tokio

Β§Testing

WsForge handlers are easy to test:

use wsforge_core::prelude::*;

async fn my_handler(msg: Message) -> Result<String> {
    Ok(format!("Echo: {}", msg.as_text().unwrap_or("")))
}

#[tokio::test]
async fn test_handler() {
    let msg = Message::text("hello");
    let result = my_handler(msg).await.unwrap();
    assert_eq!(result, "Echo: hello");
}

Β§Production Considerations

Β§Rate Limiting

use wsforge_core::prelude::*;
use std::sync::Arc;
use tokio::sync::RwLock;
use std::collections::HashMap;

struct RateLimiter {
    limits: RwLock<HashMap<String, u32>>,
}

async fn rate_limited_handler(
    msg: Message,
    conn: Connection,
    State(limiter): State<Arc<RateLimiter>>,
) -> Result<String> {
    // Check rate limit
    // Process if allowed
    Ok("processed".to_string())
}

Β§Graceful Shutdown

use wsforge_core::prelude::*;
use tokio::signal;

#[tokio::main]
async fn main() -> Result<()> {
    let router = Router::new();

    tokio::select! {
        _ = router.listen("127.0.0.1:8080") => {},
        _ = signal::ctrl_c() => {
            println!("Shutting down gracefully...");
        }
    }

    Ok(())
}

Β§Further Reading

Re-exportsΒ§

pub use connection::Connection;
pub use connection::ConnectionId;
pub use error::Error;
pub use error::Result;
pub use extractor::ConnectInfo;
pub use extractor::Data;
pub use extractor::Extension;
pub use extractor::Extensions;
pub use extractor::Json;
pub use extractor::Path;
pub use extractor::Query;
pub use extractor::State;
pub use handler::Handler;
pub use handler::HandlerService;
pub use handler::IntoResponse;
pub use handler::JsonResponse;
pub use handler::handler;
pub use message::Message;
pub use message::MessageType;
pub use middleware::LoggerMiddleware;
pub use middleware::Middleware;
pub use middleware::MiddlewareChain;
pub use middleware::Next;
pub use router::Route;
pub use router::Router;
pub use state::AppState;
pub use static_files::StaticFileHandler;

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
Commonly used types and traits for WsForge applications.
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.