Module static_files

Module static_files 

Source
Expand description

Static file serving for hybrid HTTP/WebSocket servers.

This module provides functionality to serve static files (HTML, CSS, JavaScript, images, etc.) alongside WebSocket connections on the same port. This allows you to build complete web applications where the frontend UI and WebSocket backend share a single server.

§Overview

The static file handler:

  • Serves files from a specified directory
  • Automatically detects MIME types
  • Handles index files (e.g., index.html for directory requests)
  • Prevents path traversal attacks
  • Supports percent-encoded URLs
  • Returns proper HTTP responses with status codes

§Security

The handler includes built-in security features:

  • Path traversal prevention: Attempts to access ../ or similar patterns are blocked
  • Canonical path validation: All paths are canonicalized and checked against the root
  • Access control: Only files within the configured root directory can be served

§MIME Type Detection

File types are automatically detected based on file extensions:

ExtensionMIME TypeUse Case
.htmltext/htmlWeb pages
.csstext/cssStylesheets
.jsapplication/javascriptJavaScript
.jsonapplication/jsonJSON data
.pngimage/pngPNG images
.jpg, .jpegimage/jpegJPEG images
.svgimage/svg+xmlSVG graphics
.wasmapplication/wasmWebAssembly

§Architecture

┌─────────────────┐
│  HTTP Request   │
└────────┬────────┘
         │
         ├──→ Parse URL path
         │
         ├──→ Decode percent-encoding
         │
         ├──→ Validate against root directory
         │
         ├──→ Check if directory → serve index.html
         │
         ├──→ Read file contents
         │
         └──→ Return HTTP response with MIME type

§Examples

§Basic Static File Serving

use wsforge::prelude::*;

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

let router = Router::new()
    .serve_static("public")  // Serve files from ./public directory
    .default_handler(handler(ws_handler));

// Now accessible:
// http://localhost:8080/          -> public/index.html
// http://localhost:8080/app.js    -> public/app.js
// http://localhost:8080/style.css -> public/style.css
// ws://localhost:8080             -> WebSocket handler

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

§Web Chat Application

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

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

let router = Router::new()
    .serve_static("chat-ui")  // Serve chat UI from ./chat-ui
    .default_handler(handler(chat_handler));

// Directory structure:
// chat-ui/
//   ├── index.html    <- Main chat page
//   ├── app.js        <- WebSocket client logic
//   ├── style.css     <- Chat styling
//   └── assets/
//       └── logo.png  <- Static assets

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

§Single Page Application

use wsforge::prelude::*;

async fn api_handler(msg: Message) -> Result<Message> {
    // Handle API WebSocket messages
    Ok(msg)
}

let router = Router::new()
    .serve_static("dist")  // Serve built SPA from ./dist
    .default_handler(handler(api_handler));

// Typical SPA structure:
// dist/
//   ├── index.html
//   ├── bundle.js
//   ├── styles.css
//   └── assets/

router.listen("0.0.0.0:3000").await?;

Structs§

StaticFileHandler
Handler for serving static files from a directory.

Functions§

http_response
Constructs an HTTP response with the given status, content type, and body.