Skip to main content

Crate webio

Crate webio 

Source
Expand description

§📖 Documentation



WebIO

A minimalist, high-performance Rust web framework built with a zero-dependency philosophy for maximum speed and low memory footprint.

github crates.io docs.rs license downloads

§1. Overview

WebIO addresses the "Event Loop Freeze" common in traditional asynchronous runtimes. By utilizing OS-level pre-emption, it ensures that heavy mathematical calculations or massive data parses do not block the responsiveness of the server.

§1-1. Key Technical Specs

  • Zero Dependencies: No tokio, hyper, or serde in the core.
  • Performance: ~50µs – 150µs response latency for cached assets.
  • Memory Safety: O(1) memory complexity for multi-gigabyte streams.
  • Concurrency: Go-inspired multi-threading using native OS threads.

§1-2. Why WebIO?

WebIO is a zero-dependency Rust web framework engineered to prevent “event loop freeze” during heavy calculations. By relying strictly on the Rust Standard Library, it prioritizes memory predictability and raw performance for data science and computational tasks. This minimalist engine utilizes dedicated OS threads for each connection to ensure non-blocking, pre-emptive multitasking. Featuring a “Safe-Turbo” executor with a custom spin-loop for ultra-low latency and O(1) memory complexity for big data ingestion, WebIO provides a high-integrity implementation for high-stakes environments.

§1-3. Rationale

WebIO vs. External Runtimes (Tokio/Hyper)

Most modern Rust web frameworks (like Axum or Actix) are built on top of Tokio, a high-performance asynchronous event-loop. While excellent for handling millions of idle connections (like a chat app), Tokio faces a “Cooperative Scheduling” challenge in Data Science and Computational environments.

§1-4. Event Loop Freeze Problem

In a traditional async runtime, tasks must “yield” voluntarily to the executor. If a single request performs a heavy 10-second mathematical calculation—such as a regression model, matrix inversion, or a large CSV parse—the entire event loop thread is blocked. This creates a “Stop-the-World” scenario where one heavy CPU task freezes the responses for all other users on that executor.

§1-5. WebIO Solution

WebIO is engineered as a specialized core engine for projects like [Fluxor](https://crates.io/crates/fluxor), where mathematical precision and memory predictability are the highest priority.

Go-Inspired OS Pre-emption

WebIO provides a Go-like concurrency experience but utilizes raw OS Threads for true kernel-level isolation. This ensures high efficiency for both small JSON responses and large “Big Data” streaming.

  • Safety Distinction: While WebIO adopts the "goroutine-per-request model" strategy found in Go, it enforces Rust’s Ownership Model. This provides the concurrency simplicity of Go without the unpredictable latency of a Garbage Collector (GC). Deterministic memory management ensures no “GC pauses” occur during heavy mathematical calculations, providing consistent performance for high-stakes computational tasks.

  • OS-Level Isolation: Utilizing OS Threads managed by the Kernel achieves pre-emptive multitasking. If one handler is 100% occupied by heavy math on Core 1, the OS automatically ensures other threads remain responsive on other cores. This architecture eliminates the risk of “blocking the loop.”

  • Safe-Turbo Bridge: While WebIO uses OS threads for isolation, a specialized block_on executor allows the use of async logic (like calling an external API or database) inside threads without the bloat of a massive dependency tree.

  • Zero-RAM Big Data: Raw TcpStream access enables moving 100GB+ datasets directly from the socket to disk in 64KB chunks. This bypasses the 10MB RAM safety guard, ensuring the engine remains stable under massive data ingestion.

§1-6. Performance Architecture

  • Hybrid Spin-Wait Strategy: The block_on executor uses a 150k-cycle spin-loop to catch I/O ready states in nanoseconds, maintaining sub-millisecond tail latency by bypassing OS scheduler jitter for “hot” tasks.
  • Smart RAM Cache: Transparently caches hot assets (<500KB) using an RwLock to provide ~50µs RAM-speed delivery for CSS/JS/JSON, while large files stream safely from the Disk.
  • Zero-Dependency Integrity: By strictly avoiding external crates, WebIO is immune to “supply chain attacks” and remains a pure, high-performance core for Computing Science and Mathematical applications.
  • Nagle Control: Granular builder-pattern control over TCP throughput vs. latency (set_nagle) optimizes for either real-time APIs or massive data syncs.

§2. Philosophy

WebIO provides a fully functional web engine with zero external dependencies. By strictly utilizing the Rust Standard Library, it ensures an ultra-light footprint, rapid compilation, and total memory predictability. This framework is designed for environments where Memory Predictability and Security Auditing are paramount.

§2-1. Pure Rust Commitment

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

§2-2. Architectural Pillars

  • Deterministic Concurrency: Unlike task-stealing executors, WebIO delegates each connection to a dedicated OS thread. This provides true kernel-level isolation for CPU-bound tasks, ensuring that one heavy request cannot starve the global listener.
  • Supply-Chain Security: By strictly avoiding external crates, WebIO is immune to third-party “Supply-Chain Attacks,” malicious updates, and “dependency hell.” The entire codebase remains transparent and fully auditable.
  • No Garbage Collection: Leveraging Rust’s ownership model ensures no unpredictable “GC pauses.” This deterministic memory management provides consistent performance for high-stakes computational and mathematical tasks.
  • Rapid Compilation: The absence of a massive dependency tree results in lightning-fast build times and a minimal binary footprint.

§3. Installation

Include webio in the project:

cargo add webio

Or add webio to the Cargo.toml:

[dependencies]
webio = "MAJOR.MINOR.PATCH" # replace with the actual version

§4. Quick Start

WebIO provides a highly flexible routing system. These examples demonstrate a basic server using the 4-1. Closure Pattern for rapid development and the 4-2. Handler Pattern for structured, modular applications.

§4-1. Closure Pattern

The closure pattern allows for defining logic directly within the route registration. This approach is ideal for maintaining full engine control with minimal boilerplate in smaller projects.

use webio::*;

fn main() {
    let mut app = WebIo::new();

    app.route(GET, "/", |_, _| async {
        Reply::new(StatusCode::Ok)
            .header("Content-Type", "text/plain; charset=UTF-8")
            .body("Hello from 🦅 WebIO!")
    });

    app.run("127.0.0.1", "8080");
}

§4-2. Handler Pattern

The handler pattern isolates logic into dedicated async functions. This is the recommended approach for production-grade applications to ensure the codebase remains clean and testable.

use webio::*;

// Logic isolated into a dedicated handler function
async fn hello_handler(_req: Req, _params: Params) -> Reply {
    Reply::new(StatusCode::Ok)
            .header("Content-Type", "text/html; charset=UTF-8")
            .body("<h1>Hello from 🦅 WebIO!</h1>")
}

fn main() {
    let mut app = WebIo::new();
    
    // Register the handler by name
    app.route(GET, "/", hello_handler);
    
    app.run("127.0.0.1", "8080");
}

§5. Dynamic Routing

Path variables are captured using the <key> syntax. The WebIO engine automatically parses multiple parameters into a thread-safe collection for immediate use.

  • URL Pattern: /to/<id>/path/<key>
  • Data Extraction: Values for id and key are isolated and accessible via the Params collection, facilitating complex API structures and nested resources.
use webio::*;

fn main() {
    let mut app = WebIo::new();

    // Define complex dynamic routes.
    // Example: http://localhost:8080/to/123/path/abc-789
    app.route(GET, "/to/<id>/path/<key>", |_req, params| async move {
        // Parameters are extracted from the zero-indexed collection
        let id = params.0.get("id").cloned().unwrap_or_default();
        let key = params.0.get("key").cloned().unwrap_or_default();
        
        Reply::new(StatusCode::Ok)
            .header("Content-Type", "text/html; charset=UTF-8")
            .body(format!("<h1>ID: {}, KEY: {}</h1>", id, key))
    });

    app.run("127.0.0.1", "8080");
}

§6. Modular Configuration

WebIO supports separating routing and middleware logic into dedicated setup functions to keep main clean.

§6-1. Routes Setup

Encapsulating routes in a setup_routes function allows for better organization, especially as the application grows in complexity.

use webio::*;

async fn home(_req: Req, _params: Params) -> Reply {
    Reply::new(StatusCode::Ok).body("<h1>Home Page</h1>")
}

async fn about(_req: Req, _params: Params) -> Reply {
    Reply::new(StatusCode::Ok).body("<h1>About Page</h1>")
}

async fn api_message(req: Req, _params: Params) -> Reply {
    Reply::new(StatusCode::Ok).body(format!("Received: {}", req.body))
}

// Encapsulate route registration
fn setup_routes(app: &mut WebIo) {
    app.route(GET, "/", home);                // Standard GET route
    app.route(GET, "/about", about);          // Informational route
    app.route(POST, "/api/msg", api_message); // Data ingestion route
}

fn main() {
    let mut app = WebIo::new();
    setup_routes(&mut app);
    app.run("127.0.0.1", "8080");
}

§6-2. Middlewares Setup

Middleware in WebIO acts as a Pre-flight Guard. By defining a setup_middlewares function, the engine can intercept requests for authentication, logging, or IP blacklisting before they reach the routing table.

1. Inline Closures (Directly inside setup_middlewares)

This approach is fine for quick logic when seeing all rules in one place is required.

use webio::*;

// --- Middleware Setup ---
fn setup_middlewares(app: &mut WebIo) {
    // 1. Logger
    app.use_mw(|path| {
        println!("[LOG]: Request for -> {}", path);
        None
    });

    // 2. Secret Key Middleware (Dynamic Check)
    app.use_mw(|path| {
        if path.contains("/secret/vault/") {
            // Logic: Only allow the request if the URL ends exactly with '123'
            if path.ends_with("/123") {
                println!("✅ Auth: Dynamic key 123 accepted.");
                return None; 
            } else {
                println!("❌ Auth: Unauthorized key attempted.");
                return Some(
                    Reply::new(StatusCode::Unauthorized)
                        .header("Content-Type", "text/html; charset=UTF-8")
                        .body("<h1>🚫 Access Denied: Invalid Key</h1>")
                );
            }
        }
        None
    });
}

// --- Dynamic Route Handler ---
async fn secret_handler(_req: Req, params: Params) -> Reply {
    // Extract the <key> from the URL
    let key = params.0.get("key").cloned().unwrap_or_default();
    
    Reply::new(StatusCode::Ok)
        .header("Content-Type", "text/html; charset=UTF-8")
        .body(format!("<h1>🔐 Vault Accessed</h1><p>Key used: <b>{}</b></p>", key))
}

fn main() {
    let mut app = WebIo::new();
    
    setup_middlewares(&mut app);

    // 1. Public Admin Route
    app.route(GET, "/admin/dashboard", |_r, _p| async { 
        Reply::new(StatusCode::Ok).body("Admin Panel (Public)") 
    });

    // 2. Dynamic Secret Route using <key>
    // http://localhost:8080/secret/vault/123   ==>   🔐 Vault Accessed     Key used: 123
    // http://localhost:8080/secret/vault/132   ==>   🚫 Access Denied: Invalid Key
    app.route(GET, "/secret/vault/<key>", secret_handler);

    app.run("127.0.0.1", "8080");
}

2. Separate Functions (Outside setup_middlewares)

This approach is correct for complex logic when maintaining modularity and high readability across larger projects is required.

use webio::*;

// --- 1. Middleware Logic Functions ---

fn logger_mw(path: &str) -> Option<Reply> {
    println!("[LOG]: Request for -> {}", path);
    None
}

fn auth_mw(path: &str) -> Option<Reply> {
    if path.starts_with("/protected/") {
        if path.ends_with("/123") {
            println!("✅ Auth: Protected key 123 accepted.");
            return None; 
        } else {
            return Some(
                Reply::new(StatusCode::Unauthorized)
                    .header("Content-Type", "text/html; charset=UTF-8")
                    .body("<h1>🚫 Access Denied: Invalid Key</h1>")
            );
        }
    }
    None
}

// --- 2. Route Handler Functions ---

async fn admin_handler(_req: Req, _p: Params) -> Reply {
    Reply::new(StatusCode::Ok).body("<h1>Admin Panel</h1><p>Publicly visible.</p>")
}

async fn protected_handler(_req: Req, params: Params) -> Reply {
    let key = params.0.get("key").cloned().unwrap_or_default();
    Reply::new(StatusCode::Ok)
        .header("Content-Type", "text/html; charset=UTF-8")
        .body(format!("<h1>🛡️ Protected Area</h1><p>Key: <b>{}</b></p>", key))
}

// --- 3. Modular Setup Functions ---

fn setup_middlewares(app: &mut WebIo) {
    app.use_mw(logger_mw);
    app.use_mw(auth_mw);
}

fn setup_routes(app: &mut WebIo) {
    // http://localhost:8080/admin/dashboard ==>   Admin Panel  Publicly visible.
    app.route(GET, "/admin/dashboard", admin_handler);

    // http://localhost:8080/protected/123   ==>   🛡️ Protected Area     Key used: 123
    // http://localhost:8080/protected/132   ==>   🚫 Access Denied: Invalid Key
    app.route(GET, "/protected/<key>", protected_handler);
}

// --- 4. Main Entry Point ---

fn main() {
    let mut app = WebIo::new();
    
    // Configuration Setup
    // First, apply the middleware guards
    setup_middlewares(&mut app);

    // Then, register the routes
    setup_routes(&mut app);

    app.run("127.0.0.1", "8080");
}

§6-3. Static Folder

Serving static assets like CSS, JavaScript, and images is essential for web applications. WebIo provides a simple way to map a local directory to the server root, allowing files to be linked directly in HTML.

  1. Project Structure

Organizing assets into a dedicated folder (e.g., assets) keeps the project clean. Typical layout:

my_webio_project
├───assets
│   ├───css
│   │   └───styles.css
│   ├───images
│   │   ├───favicon.ico
│   │   └───logo.svg
│   └───js
│       └───script.js
├───src
│   └───main.rs
└───Cargo.toml
  1. Implementation

Registering a directory with app.use_static("folder_name") informs the server where to look for files. For example, once the assets folder is registered, a file located at assets/css/styles.css is served directly at the URL path /css/styles.css.

use webio::*;

// HTML template linking to static assets
const CONTENT: &str = r#"<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- Paths match the structure inside the 'assets' folder -->
    <link rel="icon" type="image/x-icon" href="/images/favicon.ico">
    <link rel="stylesheet" href="/css/styles.css">
    <script defer src="/js/script.js"></script>
    <title>My WebIo Project</title>
</head>
<body>
    <a href="/">
        <img src="/images/logo.svg" alt="Logo">
    </a>
</body>
</html>"#;

async fn home_handler(_req: Req, _p: Params) -> Reply {
    Reply::new(StatusCode::Ok)
        .header("Content-Type", "text/html; charset=UTF-8")
        .body(CONTENT)
}

fn main() {
    let mut app = WebIo::new();
    
    // Map the "assets" directory to the URL root "/"
    app.use_static("assets");

    app.route(GET, "/", home_handler);

    app.run("127.0.0.1", "8080");
}

§7. Log Reply

WebIO allows for the monitoring of outgoing responses by enabling Reply Logging. When active, the engine tracks status codes and headers sent back to the client, providing better visibility into the server’s final output.

  • Optional Monitoring: Response logging is disabled by default (false) to maintain high performance and clean terminal output.
  • Debugging Insights: Enabling this feature is ideal for verifying that correct status codes (like 200 OK or 404 Not Found) are being dispatched to the end user.
use webio::*;

fn main() {
    let mut app = WebIo::new();

    // Log Reply:
    // Enable logging of outgoing responses (Replies).
    // When true, the server logs the status codes and headers sent back to the client.
    app.log_reply_enabled = true;

    // Static files and 404 handlers
    app.use_static("assets"); 
    // app.on_404(my_custom_html_404);
    // app.on_404(my_custom_json_404);

    // Routes
    // app.route(GET, "/", home_page);

    app.run("127.0.0.1", "8080");
}

§8. Application Tailoring

WebIO provides built-in methods to easily customize and personalize application behavior and visual identity.

§8-1. Custom 404 Handlers

WebIO allows overriding the default "Not Found" response. By using the on_404 method, custom logic can be registered to handle missing routes differently based on the client type.

Content-Aware Errors

The engine automatically selects the appropriate handler by checking the Accept header of the incoming request. This ensures browsers receive HTML while API tools receive JSON.

use webio::*;

// --- 1. Error Templates ---

const CUSTOM_404_HTML: &str = r#"
    <div style='text-align:center; font-family:sans-serif;'>
        <h1 style='color:red;'>404 - Not Found</h1>
        <p>That page doesn't exist on WebIo!</p>
    </div>
"#;

const CUSTOM_404_JSON: &str = r#"{"error": "not_found", "code": 404, "source": "WebIo API"}"#;

// --- 2. Handler Functions ---

/// Selected by WebIO when a browser (Accept: text/html) hits a missing route.
async fn custom_html_404(_req: Req, _params: Params) -> Reply {
    Reply::new(StatusCode::NotFound)
        .header("Content-Type", "text/html; charset=UTF-8")
        .body(CUSTOM_404_HTML)
}

/// Selected for API clients or tools like `curl`.
async fn custom_json_404(_req: Req, _params: Params) -> Reply {
    Reply::new(StatusCode::NotFound)
        .header("Content-Type", "application/json")
        .body(CUSTOM_404_JSON)
}

// --- 3. Configuration ---

fn setup_404_error(app: &mut WebIo) {
    app.on_404(custom_html_404);
    app.on_404(custom_json_404);
}

fn main() {
    let mut app = WebIo::new();
    
    // --- Application Configuration ---
    
    // 1. Pre-flight Guards
    // setup_middlewares(&mut app);

    // 2. Routing Table
    // setup_routes(&mut app);

    // 3. Error Handling
    setup_404_error(&mut app);

    app.run("127.0.0.1", "8080");
}

§8-2. Custom Startup Banner

WebIO includes a professional default banner while offering full override capabilities. Assigning a value to the banner_text field before calling .run() enables:

  • Branding & Emojis: Integration of custom icons and framework names.
  • Environment Labeling: Distinct identification for different modes (e.g., “Production Engine” vs “Dev Mode”).
  • Automatic Fallback: If the field remains empty, the engine defaults to the signature 🦅 WebIO Live: prefix to maintain a clean terminal interface.
use webio::*;

fn main () {
    let mut app = WebIo::new();

    app.route(GET, "/", |_req, _params| async {
        Reply::new(StatusCode::Ok)
            .header("Content-Type", "text/html; charset=UTF-8")
            .body("<h1>My Custom Multi-Threaded Engine</h1>")
    });

    // 1. Personalize Engine Branding.
    // Terminal Output: 🚀 My Custom Multi-Threaded Engine: http://127.0.0.1:8080
    app.banner_text = "🚀 My Custom Multi-Threaded Engine:".to_string();

    // 2. Launch the Multi-Threaded Engine.
    app.run("127.0.0.1", "8080");
}

§9. Application Settings

WebIO provides low-level control over the underlying TCP stack and memory management. These settings optimize the engine for different workloads, ranging from real-time messaging to massive data ingestion.

§9-1. Dynamic Nagle Control

Access to the Nagle Algorithm (TCP_NODELAY) allows for tuning networking behavior. This configuration is applied within the Worker Implementation during the initial connection phase.

The Strategy: Throughput vs. Latency

In handle_connection, the engine toggles the socket’s “no-delay” state based on the global configuration:

// --- TCP OPTIMIZATION ---
// set_nagle(false) -> Low Latency (Small JSON/HTML, PWA)
// set_nagle(true)  -> High Throughput (Big Data CSVs)
let _ = stream.set_nodelay(!self.nagle_enabled);
  • High Throughput (set_nagle(true)): The default mode. It buffers small outgoing packets into larger segments. Best for serving large files or reducing CPU overhead.
  • Ultra-Low Latency (set_nagle(false)): Disables buffering to send every chunk immediately. Best for WebSockets, chat interfaces, and interactive APIs.

Implementation in main

use webio::*;

fn main() {
    let mut app = WebIo::new();

    // Option A: Explicitly Enabled (High Throughput)
    app.set_nagle(true).run("0.0.0.0", "8080");

    // Option B: Explicitly Disabled (Low Latency)
    // app.set_nagle(false).run("0.0.0.0", "8080");

    // Option C: Standard Default (Nagle is ON/True)
    // app.run("0.0.0.0", "8080");
}

§9-2. RAM Safety Guards

(Pre-emptive Heap Protection)

Strict memory management prevents system exhaustion during high-concurrency or malicious “Big Data” uploads.

Pre-emptive Rejection (The 10MB Threshold)

WebIO inspects the Content-Length header before allocating memory. If a payload exceeds the 10MB safety limit, the connection is terminated immediately with a 403 Forbidden response.

use webio::*;

fn main() {
    let mut app = WebIo::new();

    app.route(POST, "/secure-upload", |req, _params| async move {
        // --- 1. DEFINE THRESHOLD ---
        let max_body_size = 10 * 1024 * 1024; // 10MB Threshold

        // --- 2. EXTRACT METADATA ---
        let content_length = req.headers.get("content-length")
            .and_then(|v| v.parse::<usize>().ok())
            .unwrap_or(0);

        // --- 3. ENFORCE GUARD ---
        if content_length > max_body_size {
            return Reply::new(StatusCode::Forbidden)
                .body("Payload Too Large (Max 10MB)");
        }

        Reply::new(StatusCode::Ok).body("Data safe for heap allocation")
    });

    app.run("0.0.0.0", "8080");
}

Protocol Significance

  • Pre-emptive Rejection: The connection is evaluated before the application attempts to buffer the body, stopping DoS attacks at the header level.
  • Zero-Waste Policy: If content_length exceeds max_body_size, the engine returns a 403 Forbidden immediately, preserving CPU and RAM for other concurrent threads.

§9-3. Thread Isolation Security

WebIO ensures that global settings and high-load tasks never compromise the stability of the entire engine. By moving every connection into a Dedicated OS Thread, the framework achieves a level of security and reliability where heavy tasks cannot interfere with lightweight ones.

Independent Context

Each connection is isolated at the operating system level. This means if a specific route (like a 10GB video upload) is utilizing 9-1 (High Throughput) or 9-2 (Streaming), it happens in total isolation from other active users.

  • No “Stop-the-World”: A heavy data stream in one thread cannot block the Nagle-disabled “Ultra-Low Latency” response of a Chat WebSocket in another thread.
  • Deterministic Reliability: Because each worker runs its own block_on executor, performance settings applied to the TcpStream (like timeouts or Nodelay) are local to that specific connection.

Performance Guarantee

By combining Dynamic Nagle Control with Thread Isolation, the application can simultaneously act as a high-speed API and a heavy-duty file server without manual resource partitioning.

# --- WORKER IMPLEMENTATION LOGIC ---

# 1. Connection arrives at the listener
# 2. WebIO spawns a dedicated OS Thread for this specific stream
# 3. Isolation ensures this stream's settings don't leak to others
stream.set_nodelay(true/false) 

# 4. Execute the asynchronous handler within a synchronous bridge
# Even if this handler takes 10 minutes (Big Data), 
# the rest of the app remains responsive.
let reply = block_on(handler(req, params))

# 5. Immediate resource reclamation upon completion

§9-4. Streaming Finalization

(Chunked Transfer & Syscall Optimization)

WebIO implements a high-performance Finalization Engine that serializes metadata and streams body fragments directly to the network interface.

Performance Architecture

  • Syscall Minimization: Utilizes a high-capacity (64KB) BufWriter to batch headers and initial data fragments. This minimizes the “Context Switch Tax” between user-space and the OS kernel, frequently enabling 50µs - 150µs response times in local environments.
  • Memory Safety: By moving data in discrete chunks, the engine prevents the allocation of massive byte vectors on the heap, ensuring a stable RAM profile regardless of file size.
  • HTTP/1.1 Chunked Encoding: This protocol foundation allows WebIO to deliver “Big Data” without requiring prior knowledge of the total payload size.

The Streaming Loop

The engine consumes chunks from the BodyStream until exhaustion, wrapping each in the RFC-standard hex-size format: shell

# --- PROTOCOL EXECUTION FLOW ---

# 1. Construct Status Line & Protocol Headers
# 2. Push directly into the 64KB Buffered Writer
"HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n"

# 3. Enter the BIG DATA STREAMING LOOP
# Protocol Format: [Hex Size]\r\n[Payload]\r\n
"1000\r\n[4096 Bytes of Data]\r\n"
"1000\r\n[4096 Bytes of Data]\r\n"

# 4. Termination: Send RFC-standard zero-length chunk
"0\r\n\r\n"

# 5. Resource Reclamation: Force OS-level socket closure
stream.shutdown(Both)
Use code with caution.

Diagnostic & Telemetry

Upon the final byte flush, the thread triggers high-resolution telemetry logging. This captures the precise duration from the initial TcpStream acceptance to the final socket shutdown, providing developers with clear insight into Request Latency.

§9-5. MIME Type Configuration

WebIO includes a built-in registry to map file extensions to their corresponding Media Types. For granular application control, the engine provides methods to add, update, or restrict specific formats. Further implementation details are available in the mime and engine source modules.

Customizing the Registry

The registry is modified directly through the WebIo instance before calling .run(). This allows for the support of modern formats or the disabling of sensitive file types.

  • Set Single Type: Add or update a specific mapping.
  • Bulk Update: Apply multiple mappings simultaneously using a vector of tuples.
  • Remove Types: Disable specific extensions to prevent the server from identifying or serving them with specific headers.
use webio::*;

fn main() {
    let mut app = WebIo::new();

    // 1. Add support for modern image formats
    app.set_mime("webp", "image/webp");

    // 2. Bulk update for web assets and fonts
    app.set_mimes(vec![
        ("woff2", "font/woff2"), 
        ("wasm", "application/wasm")
    ]);

    // 3. Security: Disable serving of specific script files
    app.remove_mime("php");

    // 4. Disable multiple video formats at once
    let to_remove = vec!["mp4", "webm", "avi", "mov"];
    app.remove_mimes(to_remove);

    app.run("127.0.0.1", "8080");
}

Internal Resolution & Fallback

The engine performs case-insensitive lookups during the request cycle. If a file extension (e.g., .JPG or .jpg) is not found in the custom or default registry, WebIO defaults to application/octet-stream to ensure a safe binary fallback. For more detailed implementation logic, check the mime and engine modules.


§10. Extensions

While WebIO remains dependency-free at its core, the ecosystem provides optional extensions to enhance developer productivity. These crates are built following the same “Pure Rust” philosophy—prioritizing performance, minimal overhead, and seamless integration with the WebIO engine.

§10-1. Forge RSX

Forge-rsx stands as a high-performance HTML macro engine for Rust. It enables type-safe, JSX-like template authoring directly within source files, compiling them into optimized strings at build time.

Core Features

  • rsx! Macro: Provides a declarative syntax for nesting HTML elements.
  • Component Logic: Supports embedding Rust expressions and variables directly into attributes or body text.
  • Zero-Cost Abstraction: Transforms templates into efficient string buffers without runtime overhead.
use webio::*;
use forge_rsx::rsx;

async fn home_page(_req: Req, _params: Params) -> Reply {
    let name = "WebIO User";
    let page = rsx! { btfy2,
        div {
            class: "container",
            h1 { "Welcome, "{name} }
            p { "Fast, dependency-free rendering." }
        }
    };

    Reply::new(StatusCode::Ok)
        .header("Content-Type", "text/html; charset=UTF-8")
        .body(page)
}

fn main () {
    let mut app = WebIo::new();

    app.route(GET, "/", home_page);

    app.run("127.0.0.1", "8080");
}

§10-2. WebIo Macros

webio_macros provides procedural macro support to reduce boilerplate. It introduces attribute-based routing and streamlined handler definitions, making the codebase cleaner for large-scale applications.

Core Features

  • #[webio_main]: Enables the definition of an application entry point using standard async fn main() syntax.
  • Turbo Performance: Wraps code in the webio::block_on engine, maintaining 70µs - 400µs response times.
  • replace!: A versatile tool for substituting {{key}} placeholders in any content.
  • html!: Acts as a semantic alias for web-specific development.
use webio::*;
use webio_macros::{webio_main, html};

#[webio_main]
async fn main() {
    let mut app = WebIo::new();

    // Enable live performance logging
    app.log_reply_enabled = true;

    // Standard Async Route: No 'block_on' needed inside #[webio_main]
    app.route(GET, "/", |_req, _params| async {
        // Using the 'html!' macro for clean, reactive-style templating
        let content = html!("<h1>Hello from 🦅 {{name}}!</h1>", name = "WebIO");
        
        Reply::new(StatusCode::Ok)
            .header("Content-Type", "text/html; charset=UTF-8")
            .body(content)
    });

    // Configuration and Launch
    app.set_nagle(false).run("0.0.0.0", "8080");
}

Live Output Preview

The terminal provides real-time monitoring of every incoming request. With app.log_reply_enabled set to true, you get a clear view of the HTTP method, requested path, status code, and precise execution time.

🦅 WebIO Live: http://0.0.0.0:8080
[16:27:13] GET /no-block-on -> 404 (1.9506ms)
[16:27:17] GET / -> 200 (79.9µs)
[16:27:19] GET / -> 200 (236.4µs)
[16:27:19] GET / -> 200 (97.6863ms)
[16:27:20] GET / -> 200 (139.1µs)

Performance Breakdown

The Live Output Preview reflects the engine’s efficiency:

  • Ultra-Low Latency: The second request completed in just 79.9µs (microseconds). This represents the raw speed of the WebIO routing engine and the zero-overhead html! macro.
  • Smart 404 Handling: The request to /no-block-on correctly returned a 404 in 1.95ms, demonstrating active monitoring and routing for missing endpoints.
  • Cold Start vs. Hot Cache: Variations in time (such as the 97.6ms entry) typically account for initial TCP handshakes or browser-side resource loading. Consistent 139.1µs entries confirm the sustained “warm” performance of the Rust binary.

§10-3. Crator

Crator is the official Rust high-performance toolkit for HTTP/HTTPS requests, JSON processing, and environment management.

Core Features

  • HTTP/HTTPS Clien: A lightweight, high-performance, and synchronous HTTP/HTTPS client for Rust.
  • JSON extractor: A lightweight, zero-dependency JSON extractor designed for maximum performance and efficiency.
  • rsj! macro: High-performance, zero-dependency rsj! macro for declarative, JSX-like JSON generation with support for loops and conditionals.
  • Crates.io API Metadata: High-performance functions to fetch and interact with structured Crates.io API metadata.
  • Env: Panic-free utilities for safely loading and managing environment variables.

Directory Structure

my_webio_project/
├── .env                <-- Environment Config (External to src/)
├── Cargo.toml          <-- Manifest & Dependencies
├── src/                
│   └── main.rs         <-- WebIO + Crator Logic
└── target/             <-- Compiled Binaries  

Main Application Code

The following implementation integrates dynamic User-Agent identities and environment-driven port configuration.

use webio::*;
use crator::{Http, Json, rsj, get_env_or};

async fn get_crate_metadata(_req: Req, params: Params) -> Reply {
    // 1. URL Path Definition: Targets the specific crates.io API endpoint.
    let crate_name = params.0.get("name").cloned().unwrap_or_else(|| "crator".into());
    let url = format!("https://crates.io/api/v1/crates/{}", crate_name);
    
    // 2. Dynamic Identity: Use 'get_env_or' to set the User-Agent identity.
    // Fallback defaults to "crator-client/0.1.0" if no env variable is found.
    let user_agent = get_env_or("APP_UA", "crator-client/0.1.0").to_string();

    // 3. HTTP Request: Crator client with mandatory User-Agent and timeout.
    let response_result = Http::get(&url)
        .header("User-Agent", user_agent)
        .timeout(10)
        .send("");

    match response_result {
        Ok(res) if res.status() == 200 => {
            // 4. Parse JSON with crator::Json: Zero-dependency extraction.
            let raw_json = Json::from_str(res.body());
            
            let name = raw_json["crate"]["id"].as_str().unwrap_or("unknown");
            let downloads = raw_json["crate"]["downloads"].as_f64().unwrap_or(0.0);

            // 5. Build response with rsj! ('tabed' mode): Provides formatted JSON output.
            let output = rsj!(tabed, obj {
                crate_id: name,
                total_downloads: downloads,
                status: "success"
            });

            Reply::new(StatusCode::Ok)
                .header("Content-Type", "application/json; charset=UTF-8")
                .body(output.to_string())
        }
        Ok(res) => {
            Reply::new(StatusCode::NotFound)
                .header("Content-Type", "text/plain; charset=UTF-8")
                .body(format!("API Error: Status {}", res.status()))
        }
        Err(e) => {
            Reply::new(StatusCode::InternalServerError)
                .header("Content-Type", "text/plain; charset=UTF-8")
                .body(format!("❌ Connection Error: {}", e))
        }
    }
}

fn main() {
    let mut app = WebIo::new();
    
    // Route matching for dynamic crate metadata retrieval.
    // Access via: http://localhost:8080/api/info/webio
    app.route(GET, "/api/info/<name>", get_crate_metadata);

    // 6. Environment Configuration: Dynamic port retrieval with standard fallback.
    let host = "127.0.0.1";
    let port = get_env_or("PORT", "8080");

    app.run(&host, &port);
}

§11. Deployment

Deploying a WebIO application with the Crator toolkit involves specific network configurations and environment management. Below is the breakdown of deployment methods and technical requirements.

§11-1. Deployment Methods

  • PaaS (Platform as a Service): These services often manage the underlying infrastructure automatically. They typically assign a dynamic port via environment variables at runtime.
  • VPS (Virtual Private Server): For these environments, Docker is the recommended standard to ensure consistency between development and production.
  • Serverless / Cloud Functions: Some specialized providers allow Rust binaries to run as ephemeral functions within serverless or cloud function environments.

§11-2. Host and Port Configuration

The transition from development to production requires modifying the listener address to allow external traffic.

  1. Address Binding: The host must change from 127.0.0.1 (localhost) to 0.0.0.0. This tells the application to listen on all available network interfaces.
  2. Port Selection: The port must align with the provider’s specific requirements.
    • Fixed Ports: Some setups allow a static port (e.g., 8080 or 80).
    • Dynamic Ports: Many free tiers or managed services assign a unique port automatically.
  3. Implementation: Use crator::get_env_or to bridge the gap between static code and dynamic provider requirements.
use webio::*;
// use crator::get_env_or;

fn main() {
    let mut app = WebIo::new();

    // ... define routes ...

    app.run("0.0.0.0", "8080"); // Change to the required port

    // or:

    // 1. Host: Change from "127.0.0.1" to "0.0.0.0" for production.
    // let host = "0.0.0.0"; 
    
    // 2. Port: Dynamically pull from the environment (required by most PaaS)
    // or fallback to a default (e.g., "10000").
    // let port = get_env_or("PORT", "10000"); 

    // 3. Execution: Pass references to the host and port.
    // app.run(&host, &port);
}

§11-3. Environment Variables

If the project relies on external configurations (API keys, database URLs, or the APP_UA identity mentioned in the Crator logic), environment variables must be handled according to the deployment type:

  • Local / Docker: Keep the .env file in the root directory as shown in the 10-3. Crator directory structure.
  • Managed Hosts: Most providers require entering these variables directly into their internal “Environment” or “Secrets” dashboard rather than uploading a physical file.
  • Security: Ensure the .env file is included in .gitignore to prevent leaking sensitive credentials during the deployment process.

§12. License

WebIO is distributed under the MIT License. This allows for free use, modification, and distribution in both open-source and commercial projects.

MIT License

Copyright (c) 2026 Montasir Mirghani

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Re-exports§

pub use crate::core::*;
pub use crate::crypto::*;
pub use crate::engine::*;
pub use crate::mime::*;
pub use crate::utils::*;

Modules§

core
WebIO Core Engine
crypto
WebIO Cryptographic Engine
engine
WebIO Orchestration Engine
mime
MIME Module
utils
WebIO Utility & Protocol Engine