Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Chapter 20: HTTP Server - Production-Ready Static File Serving

Ruchy includes a production-ready HTTP server optimized for static file serving and WASM applications. This chapter demonstrates how to use the ruchy serve command for local development and production deployment.

Overview

The Ruchy HTTP server provides:

  • 12.13x faster throughput than Python http.server (empirically validated)
  • Automatic MIME type detection for HTML, CSS, JS, JSON, and WASM files
  • WASM optimization with automatic COOP/COEP headers for SharedArrayBuffer
  • Multi-threaded async runtime with CPU-count workers
  • Memory safety (Rust guarantees - no segfaults)
  • Energy efficiency (16x better req/CPU% ratio than Python)

Basic Usage

Serving Current Directory

# Serve current directory on default port 8080
ruchy serve .

# Access at http://127.0.0.1:8080

Custom Port and Host

# Serve on custom port
ruchy serve ./public --port 3000

# Bind to all interfaces (0.0.0.0 for external access)
ruchy serve ./dist --port 8080 --host 0.0.0.0

# Production deployment
ruchy serve ./static --port 80 --host 0.0.0.0

Example: Static Website

Directory Structure

my-website/
├── index.html
├── style.css
├── app.js
└── assets/
    ├── logo.png
    └── module.wasm

index.html

<!DOCTYPE html>
<html>
<head>
    <title>My Website</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <h1>Welcome to My Website</h1>
    <p>Served by Ruchy HTTP Server</p>
    <script src="app.js"></script>
</body>
</html>

style.css

body {
    font-family: system-ui, sans-serif;
    max-width: 800px;
    margin: 0 auto;
    padding: 2rem;
    background: #f5f5f5;
}

h1 {
    color: #333;
}

app.js

console.log('Website loaded successfully!');

document.addEventListener('DOMContentLoaded', () => {
    console.log('DOM ready');
});

Start Server

# Navigate to website directory
cd my-website

# Start server
ruchy serve . --port 8080

# Output:
# ✅ Server started successfully (8 worker threads, optimized async runtime)
# 📂 Serving: /home/user/my-website
# 🌐 Listening: http://127.0.0.1:8080

WASM Application Support

The Ruchy HTTP server automatically adds WASM-specific headers for optimal performance.

Example: WASM Module

wasm-app/
├── index.html
├── app.wasm
└── loader.js

index.html

<!DOCTYPE html>
<html>
<head>
    <title>WASM Application</title>
</head>
<body>
    <h1>WebAssembly Application</h1>
    <div id="output"></div>
    <script src="loader.js"></script>
</body>
</html>

loader.js

// Ruchy HTTP server automatically sets:
// - Content-Type: application/wasm (enables streaming compilation)
// - Cross-Origin-Opener-Policy: same-origin
// - Cross-Origin-Embedder-Policy: require-corp
//
// These headers enable SharedArrayBuffer for multi-threaded WASM

async function loadWasm() {
    try {
        // Streaming compilation (fast!)
        const response = await fetch('app.wasm');
        const module = await WebAssembly.instantiateStreaming(response);

        console.log('WASM module loaded successfully!');
        document.getElementById('output').textContent = 'WASM Ready!';
    } catch (error) {
        console.error('Failed to load WASM:', error);
    }
}

loadWasm();

Start WASM Server

cd wasm-app
ruchy serve . --port 8080

# WASM files automatically get:
# ✅ Content-Type: application/wasm
# ✅ COOP: same-origin (SharedArrayBuffer support)
# ✅ COEP: require-corp (security isolation)

Performance Characteristics

Empirically Validated Benchmarks

Based on 1,000 requests with 50 concurrent connections:

MetricRuchyPython http.serverSpeedup
Throughput4,497 req/s371 req/s12.13x faster
Latency9.11ms63.48ms7x lower
Memory8.6 MB18.4 MB2.13x efficient
Energy333 req/CPU%21 req/CPU%16x efficient

When to Use Ruchy HTTP Server

Excellent For:

  • Local development (fast, reliable)
  • Static website hosting
  • WASM application serving
  • Single-page applications (SPAs)
  • API mock servers (with static JSON)
  • Production static file CDN

Not Designed For:

  • Dynamic server-side rendering (use Axum/Actix directly)
  • Database-backed applications (use full web framework)
  • Complex routing logic (use Axum router)

Production Deployment Example

Systemd Service (Linux)

Create /etc/systemd/system/ruchy-web.service:

[Unit]
Description=Ruchy HTTP Server
After=network.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/mysite
ExecStart=/usr/local/bin/ruchy serve /var/www/mysite --port 8080 --host 127.0.0.1
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable ruchy-web
sudo systemctl start ruchy-web
sudo systemctl status ruchy-web

Combine Ruchy with Nginx for SSL termination and caching:

server {
    listen 80;
    listen 443 ssl http2;
    server_name mywebsite.com;

    # SSL configuration
    ssl_certificate /etc/letsencrypt/live/mywebsite.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mywebsite.com/privkey.pem;

    # Proxy to Ruchy HTTP server
    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # Cache static assets
    location ~* \.(css|js|png|jpg|jpeg|gif|ico|wasm)$ {
        proxy_pass http://127.0.0.1:8080;
        proxy_cache_valid 200 1d;
        add_header Cache-Control "public, immutable";
    }
}

Precompressed File Optimization

Ruchy automatically serves precompressed files if available:

Directory Structure

optimized-site/
├── index.html
├── index.html.gz     # Gzip compressed
├── index.html.br     # Brotli compressed
├── app.js
├── app.js.gz
└── app.js.br

Create Precompressed Files

# Gzip compression
find . -type f \( -name "*.html" -o -name "*.css" -o -name "*.js" \) \
    -exec gzip -9 -k {} \;

# Brotli compression (even better)
find . -type f \( -name "*.html" -o -name "*.css" -o -name "*.js" \) \
    -exec brotli -9 {} \;

When a client requests index.html and supports br encoding, Ruchy automatically serves index.html.br with appropriate Content-Encoding headers.

Testing and Validation

Manual Testing

# Start server
ruchy serve ./test-files --port 8080

# Test with curl
curl http://127.0.0.1:8080/index.html

# Check WASM headers
curl -I http://127.0.0.1:8080/module.wasm

# Expected output:
# HTTP/1.1 200 OK
# content-type: application/wasm
# cross-origin-opener-policy: same-origin
# cross-origin-embedder-policy: require-corp

Load Testing

# Install wrk
sudo apt install wrk

# Benchmark with 12 threads, 400 connections, 30 seconds
wrk -t12 -c400 -d30s http://127.0.0.1:8080/index.html

# Example output:
# Running 30s test @ http://127.0.0.1:8080/index.html
#   12 threads and 400 connections
#   Thread Stats   Avg      Stdev     Max   +/- Stdev
#     Latency     9.11ms    3.24ms   50.00ms   87.21%
#     Req/Sec   4.50k   432.11     5.12k    68.34%
#   4,497 requests in 30.00s, 12.45MB read
# Requests/sec:   4497.23
# Transfer/sec:    424.83KB

Common Patterns

Development Workflow

# Terminal 1: Start server with hot reload (manual restart)
ruchy serve ./src --port 3000

# Terminal 2: Make changes, restart server
# (Auto-reload coming in future versions)

CI/CD Integration

# .github/workflows/deploy.yml
name: Deploy Static Site

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Install Ruchy
        run: cargo install ruchy

      - name: Build static site
        run: ./build.sh

      - name: Deploy to server
        run: |
          rsync -avz ./dist/ user@server:/var/www/site/
          ssh user@server 'systemctl restart ruchy-web'

Troubleshooting

Port Already in Use

# Error: Address already in use (os error 98)

# Find process using port 8080
lsof -i :8080

# Kill process
kill <PID>

# Or use different port
ruchy serve . --port 8081

Permission Denied (Port 80/443)

# Ports < 1024 require root/sudo
sudo ruchy serve . --port 80

# Or use capability (Linux)
sudo setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/ruchy
ruchy serve . --port 80  # No sudo needed

WASM Not Loading (CORS/Headers)

# Check WASM file is served correctly
curl -I http://127.0.0.1:8080/app.wasm | grep -i "content-type"

# Should show:
# content-type: application/wasm

# Check COOP/COEP headers
curl -I http://127.0.0.1:8080/app.wasm | grep -i "cross-origin"

# Should show:
# cross-origin-opener-policy: same-origin
# cross-origin-embedder-policy: require-corp

Summary

The Ruchy HTTP server provides a production-ready solution for static file serving:

  • 12.13x faster than Python http.server
  • Automatic MIME detection for all common file types
  • WASM-optimized with COOP/COEP headers
  • Memory safe (Rust guarantees)
  • Energy efficient (16x better req/CPU%)
  • Production ready with comprehensive testing

Use ruchy serve for:

  • Local development
  • Static website hosting
  • WASM application serving
  • Production deployment (with Nginx proxy)

See Chapter 23: REPL & Object Inspection for interactive development tools.

Further Reading