phantom-frame 0.1.4

A high-performance prerendering proxy engine with caching support
Documentation

phantom-frame

A high-performance prerendering proxy engine written in Rust. Cache and serve prerendered content with ease.

Features

  • 🚀 Fast caching proxy - Cache prerendered content and serve it instantly
  • 🔧 Dual mode operation - Run as standalone HTTP server or integrate as a library
  • 🔄 Dynamic cache refresh - Trigger cache invalidation via control endpoint or programmatically
  • 🔐 Optional authentication - Secure control endpoints with bearer token auth
  • Async/await - Built on Tokio and Axum for high performance
  • 📦 Easy integration - Simple API for library usage

Usage

Mode 1: Standalone HTTP Server

Run as a standalone server with a TOML configuration file:

./phantom-frame ./config.toml

Configuration File (config.toml)

[server]
# Control port for cache management endpoints (default: 17809)
control_port = 17809

# Proxy port for serving prerendered content (default: 3000)
proxy_port = 3000

# The backend URL to proxy requests to (default: http://localhost:8080)
proxy_url = "http://localhost:8080"

# Optional: Bearer token for control endpoint authentication
# If set, requests to /refresh-cache must include: Authorization: Bearer <token>
control_auth = "your-secret-token-here"

Control Endpoints

POST /refresh-cache - Trigger cache invalidation

# Without authentication
curl -X POST http://localhost:17809/refresh-cache

# With authentication (if control_auth is set)
curl -X POST http://localhost:17809/refresh-cache \
  -H "Authorization: Bearer your-secret-token-here"

Mode 2: Library Integration

Add to your Cargo.toml:

[dependencies]
phantom-frame = { path = "../phantom-frame" }
tokio = { version = "1.40", features = ["full"] }
axum = "0.7"

Use in your code:

use phantom_frame::{create_proxy, cache::RefreshTrigger};
use axum::Router;

#[tokio::main]
async fn main() {
    // Create proxy - proxy_url is the backend server to proxy requests to
    let (proxy_app, refresh_trigger): (Router, RefreshTrigger) = 
        create_proxy("http://localhost:8080".to_string());
    
    // Clone and use the refresh_trigger anywhere in your app
    let trigger_clone = refresh_trigger.clone();
    
    // Trigger cache refresh programmatically
    tokio::spawn(async move {
        // Your custom logic here
        trigger_clone.trigger();
    });
    
    // Start the proxy server
    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000")
        .await
        .unwrap();
    
    axum::serve(listener, proxy_app).await.unwrap();
}

Building

# Build the project
cargo build --release

# Run in development
cargo run -- ./config.toml

# Run the library example
cargo run --example library_usage

How It Works

  1. Request Flow: When a request comes in, phantom-frame first checks if the content is cached
  2. Cache Miss: If not cached, it fetches from the backend, caches the response, and returns it
  3. Cache Hit: If cached, it serves the cached content immediately
  4. Cache Refresh: The cache can be invalidated via the control endpoint or programmatically

API Reference

Library API

create_proxy(proxy_url: String) -> (Router, RefreshTrigger)

Creates a proxy router and refresh trigger.

  • Parameters: proxy_url - The backend server URL to proxy requests to
  • Returns: Tuple of (Router, RefreshTrigger)

RefreshTrigger

A clonable trigger for cache invalidation.

  • trigger() - Trigger a cache refresh
  • subscribe() - Subscribe to refresh events (returns a broadcast receiver)

Control Endpoints

POST /refresh-cache

Triggers cache invalidation. Requires Authorization: Bearer <token> header if control_auth is configured.

License

See LICENSE file for details