webio 0.5.0-alpha

A minimalist, high-performance web framework for Rust built with a zero-dependency philosophy.
Documentation

WebIO πŸ¦…

A minimalist, high-performance web framework for Rust built with a zero-dependency philosophy.


πŸ§ͺ Research Status: Experimental

WebIO is currently in an active research and development phase.

  • API Stability: Expect breaking changes as we refine the core engine.
  • Goal: To provide a high-integrity core engine for Data Science, Computing Science, and frameworks like Fluxor.
  • Production Warning: Use with caution until the stable 1.0.0 released.

🎯 Core Philosophy

WebIO provides a fully functional web engine with zero external dependencies. By strictly utilizing the Rust std library, it ensures an ultra-light footprint, rapid compilation, and total memory predictability. zero external dependencies.

  • No tokio, async-std or hyper.
  • No serde or heavy middleware bloat.
  • No unsafe code in the executor.
  • Just pure, high-performance Rust.

πŸ› οΈ Installation

Add this to your Cargo.toml:

[dependencies]

webio = "0.5.0-alpha"

πŸš€ What's New in v0.5.0-alpha

The v0.5.0-alpha release represents a major architectural shift from a single-threaded async model to a High-Performance Multi-threaded Hybrid Engine inspired by the Go concurrency model.

🧡 Go-Inspired Multi-threading

WebIO now mimics the Go strategy by spawning a unique OS Thread for every incoming connection. This ensures Pre-emptive Multitasking: a heavy mathematical calculation on one thread will never "freeze" the server for other usersβ€”a common pitfall in traditional async runtimes like Tokio.

⚑ Safe-Turbo block_on Executor

We have replaced the legacy runtime with a specialized Safe-Turbo Bridge. It utilizes a 150,000-cycle spin-loop to catch I/O ready states in nanoseconds. This bypasses OS scheduler jitter, maintaining sub-millisecond tail latency (~200Β΅s) while remaining 100% safe.

πŸ›‘οΈ RAM Safety & Big Data Streaming

  • 10MB Safety Valve: A pre-emptive RAM guard protects the heap by rejecting massive payloads before they are ingested.
  • Zero-RAM Ingestion: Handlers now have direct access to the TcpStream, allowing multi-gigabyte files (CSVs, Videos, Datasets) to be moved directly to disk in 64KB chunks with O(1) memory complexity.

πŸ›°οΈ Real-Time WebSockets & Global Broadcast

Full RFC 6455 compliance is now built-in. WebIO handles the cryptographic handshake (SHA-1/Base64) and binary framing manually. The new Global Client Registry allows any thread to broadcast messages to all connected users simultaneously.

🧠 Smart Asset Caching

Introduced an RwLock RAM Cache for static assets. Small files (<500KB) are served at RAM speeds (~50Β΅s), while larger files are intelligently served via the OS Page Cache to prevent memory exhaustion.

πŸ“ˆ Dynamic Nagle Control

New builder-pattern support for set_nagle(bool). Toggle between Low Latency (TCP_NODELAY) for real-time APIs or High Throughput for massive data synchronization.

🧬 Concurrency Comparison

Feature Traditional Async (Tokio) WebIO v0.5.0 (OS Threads)
Heavy Math ❌ Blocks the Event Loop βœ… Isolated per CPU Core
Tail Latency ⚠️ Variable (Task Stealing) βœ… Ultra-Low (Spin-Wait)
Memory ⚠️ Managed by Runtime βœ… Deterministic (Ownership)
Dependencies ❌ Hundreds βœ… Zero (std only)

πŸš€ Big Data POST Examples

In WebIO, standard POST data is limited to 10MB for RAM safety. For datasets exceeding this (e.g., 10GB CSVs or Videos), handlers must use the raw stream for Zero-RAM Ingestion.

use webio::*;

use std::io::{Write, Read, BufWriter};
use std::fs::File;

const INDEX_HTML: &str = r##"<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>WebIO | High-Performance Rust</title>
    <link rel="icon" href="/images/favicon.ico" type="image/x-icon" />
    <link rel="stylesheet" href="/css/styles.css" />
</head>
<body>
    <main>
        <h1>πŸ‘‹ Welcome to WebIO</h1>
        <p>A zero-dependency, ultra-low-latency web framework.</p>
        
        <section class="gallery">
            <img src="/images/logo.svg" alt="WebIO Logo" width="150" />
        </section>
    </main>
    <script src="/js/script.js"></script>
</body>
</html>"##;

// --- Implementation Examples ---

/// Demonstrates basic GET routing.
async fn hello_get_handler(_req: Req, _params: Params) -> Reply {
    Reply::new(StatusCode::Ok)
        .header("Content-Type", "text/html; charset=UTF-8")
        .body(INDEX_HTML)
}

/// Demonstrates dynamic path parameters using `<name>`.
/// Extracted via the `Params` collection.
async fn user_handler(_req: Req, params: Params) -> Reply {
    let name = params.0.get("name").cloned().unwrap_or("Guest".to_string());
    Reply::new(StatusCode::Ok).
        header("Content-Type", "text/html; charset=UTF-8")
            .body(format!("<h1>Hello πŸ‘‹, {}!</h1>", name))
}

/// A specialized handler for numeric IDs or other dynamic segments.
async fn id_handler(_req: Req, params: Params) -> Reply {
    let id = params.0.get("id").cloned().unwrap_or("0".to_string());
    Reply::new(StatusCode::Ok)
        .header("Content-Type", "text/html; charset=UTF-8")
        .body(format!("<h1>πŸ‘‹ ID: {}</h1>", id))
}

/// Demonstrates handling POST data directly from the `Req` struct.
async fn create_user_handler(req: Req, _params: Params) -> Reply {
    // Access the POST body directly
    Reply::new(StatusCode::Ok)
        .header("Content-Type", "text/html; charset=UTF-8")
        .body(format!("<h1>πŸ‘‹ User Created with Data: {}</h1>", req.body))
}

/// A typical API endpoint returning JSON content.
async fn status_handler(_req: Req, _params: Params) -> Reply {
    Reply::new(StatusCode::Ok)
        .header("Content-Type", "application/json")
        .body("{\"status\": \"online\"}")
}

/// A protected resource example. Access is controlled by the middleware defined in `main`.
async fn secret_handler(_req: Req, _params: Params) -> Reply {
    Reply::new(StatusCode::Ok)
        .header("Content-Type", "text/html; charset=UTF-8")
        .body("<h1>πŸ”“ Access Granted: Welcome Boss! πŸ’Ž</h1>")
}

/// A custom 404 handler that serves a styled HTML page.
/// Automatically selected by WebIO when a browser (Accept: text/html) hits a missing route.
async fn my_custom_html_404(_req: Req, _params: Params) -> Reply {
    Reply::new(StatusCode::NotFound)
        .header("Content-Type", "text/html; charset=UTF-8")
        .body("<h1 style='color:red;'>πŸ›Έ 404 - That page doesn't exist on WebIo!</h1>")
}

/// A custom 404 handler that serves a JSON error.
/// Automatically selected for API clients or tools like `curl`.
async fn my_custom_json_404(_req: Req, _params: Params) -> Reply {
    Reply::new(StatusCode::NotFound)
        .header("Content-Type", "application/json")
        .body("{\"error\": \"not_found\", \"code\": 404, \"source\": \"WebIo API\"}")
}

async fn handle_big_csv(mut req: Req, _params: Params) -> Reply {
    let mut file = std::fs::File::create("huge_dataset.csv").unwrap();
    // Use a small 64KB buffer to move 10GB of data
    let mut buffer = [0; 65536]; 
    while let Ok(n) = req.stream.read(&mut buffer) {
        if n == 0 { break; }
        file.write_all(&buffer[..n]).unwrap();
    }
    Reply::new(StatusCode::Ok).body("Upload Complete")
}

async fn handle_video_upload(mut req: Req, _params: Params) -> Reply {
    // 1. Create the destination file
    let file_path = "uploads/video_data.mp4";
    let file = match File::create(file_path) {
        Ok(f) => f,
        Err(_) => return Reply::new(StatusCode::InternalError).body("Could not create file"),
    };

    let mut writer = BufWriter::new(file);
    let mut buffer = [0; 65536]; // 64KB Chunk (High Throughput)
    let mut total_bytes = 0;

    // 2. Stream directly from the RAW socket (req.stream)
    // This bypasses the 10MB RAM limit entirely!
    while let Ok(n) = req.stream.read(&mut buffer) {
        if n == 0 { break; } // Socket closed or upload finished
        if let Err(_) = writer.write_all(&buffer[..n]) {
            return Reply::new(StatusCode::InternalError).body("Disk Write Error");
        }
        total_bytes += n as u64;
    }

    let _ = writer.flush();

    Reply::new(StatusCode::Ok)
        .header("Content-Type", "application/json")
        .body(format!(r#"{{"status": "success", "bytes_saved": {}}}"#, total_bytes))
}

async fn chat_handler(req: Req, _params: Params) -> Reply {
    // 1. Upgrade to WebSocket
    if let Some(mut ws) = req.upgrade_websocket() {
        
        // 2. Register the connection in our Global Registry
        if let Ok(mut clients) = CLIENTS.lock() {
            if let Ok(clone) = ws.try_clone() {
                clients.push(clone);
            }
        }

        // 3. Enter the persistent Loop (Isolated on this OS Thread)
        loop {
            // Read binary frames from the browser
            match WSFrame::read(&mut ws) {
                Ok(frame) => {
                    let msg = String::from_utf8_lossy(&frame.payload);
                    // Broadcast to ALL other threads
                    broadcast(&format!("User {}: {}", msg, req.path));
                }
                Err(_) => break, // Disconnect
            }
        }
    }
    
    // 4. Return empty (Stream is closed or hijacked)
    Reply::new(StatusCode::Ok).body("")
}

fn main() {
    let mut app = WebIo::new();
    app.log_reply_enabled = true;
    app.use_static("assets");

    app.on_404(my_custom_html_404);
    app.on_404(my_custom_json_404);

    // --- Routes ---
    app.route(GET, "/", hello_get_handler);
    app.route(GET, "/status", status_handler);
    app.route(GET, "/user/create", create_user_handler);
    app.route(GET, "/secret-handler", secret_handler);
    app.route(GET, "/user/<name>", user_handler);
    app.route(GET, "/req/<id>", id_handler);
    
    // WebSockets & Big Data (Persistent/Heavy)
    app.route(GET, "/chat", chat_handler); 
    app.route(POST, "/csv", handle_big_csv);
    app.route(POST, "/video-upload", handle_video_upload);

    // --- Start ---
    // Start the Multi-Threaded TCP Listener

    // // set false or true
    app.set_nagle(true)
       .run("0.0.0.0", "8080");

    // // set false or true
    // app = app.set_nagle(false);
    // app.run("0.0.0.0", "8080");

    // Default value nagle is on/true
    // app.run("0.0.0.0", "8080");
}