Lightweight, embeddable HTTP reverse proxy written in Rust with Caddy-like configuration syntax.
- Embeddable Library: Use as a library in your Rust applications or run as standalone CLI
- Caddy-like Configuration: Simple, human-readable configuration format
- Path-based Routing: Pattern matching with wildcard support
- Header Manipulation: Add, modify, or remove headers
- URI Rewriting: Replace parts of request URIs
- HTTP/HTTPS Backend Support: Full support for both HTTP and HTTPS backends
- Method-based Routing: Different behavior for different HTTP methods
- Direct Responses: Respond with custom status codes and bodies
- Authentication Module: Token validation and header substitution
- Management API: REST API for runtime configuration management (optional feature)
# Install via cargo
cargo install --path .
# Or build and run directly
cargo build --release
./target/release/tiny-proxy --config config.caddyAdd to your Cargo.toml:
[dependencies]
tiny-proxy = "0.1"Run as standalone server:
tiny-proxy --config config.caddy --addr 127.0.0.1:8080--config, -c: Path to configuration file (default:./file.caddy)--addr, -a: Address to listen on (default:127.0.0.1:8080)
use tiny_proxy::{Config, Proxy};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Load configuration from file
let config = Config::from_file("config.caddy")?;
// Create and start proxy
let proxy = Proxy::new(config);
proxy.start("127.0.0.1:8080").await?;
Ok(())
}Run proxy in background while doing other work:
use tiny_proxy::{Config, Proxy};
use std::sync::Arc;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let config = Config::from_file("config.caddy")?;
let proxy = Arc::new(Proxy::new(config));
// Spawn proxy in background
let handle = tokio::spawn(async move {
if let Err(e) = proxy.start("127.0.0.1:8080").await {
eprintln!("Proxy error: {}", e);
}
});
// Do other work here...
handle.await?;
Ok(())
}Update configuration at runtime:
use tiny_proxy::{Config, Proxy};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let config = Config::from_file("config.caddy")?;
let mut proxy = Proxy::new(config);
proxy.start("127.0.0.1:8080").await?;
// Later, update configuration
let new_config = Config::from_file("new-config.caddy")?;
proxy.update_config(new_config);
Ok(())
}tiny-proxy uses a Caddy-like configuration format.
site_address {
directive1 arg1 arg2
directive2 {
nested_directive
}
}Forward requests to a backend server.
localhost:8080 {
reverse_proxy http://backend:3000
}Match paths with pattern (supports wildcard *).
localhost:8080 {
handle_path /api/* {
reverse_proxy api-service:8000
}
}Replace part of the request URI.
localhost:8080 {
uri_replace /old-path /new-path
reverse_proxy backend:3000
}Add or modify request headers.
localhost:8080 {
header X-Request-ID {uuid}
header X-Custom-Header custom-value
reverse_proxy backend:3000
}Apply directives based on HTTP method.
localhost:8080 {
method GET HEAD {
respond 200 "OK"
}
reverse_proxy backend:3000
}Return a direct response with custom status and body.
localhost:8080 {
respond 200 "Service is healthy"
}localhost:8080 {
reverse_proxy http://backend:3000
}api.example.com {
reverse_proxy http://api-service:8000
}
static.example.com {
reverse_proxy http://static-service:8001
}localhost:8080 {
handle_path /api/v1/* {
handle_path /users/* {
reverse_proxy http://user-service:8001
}
reverse_proxy http://api-service:8000
}
reverse_proxy http://default-backend:3000
}localhost:8080 {
header X-Forwarded-For {header.X-Forwarded-For}
header X-Request-ID {uuid}
uri_replace /api /backend
reverse_proxy http://backend:3000
}localhost:8080 {
method GET HEAD {
respond 200 "OK"
}
reverse_proxy http://backend:3000
}Use placeholders in header values:
{header.Name}- Value of request header with that name{env.VAR}- Value of environment variable{uuid}- Random UUID
cli- Command-line interface supporttls- HTTPS backend supportapi- Management API for runtime configuration
# Minimal - core proxy only (for embedding in other applications)
[dependencies]
tiny-proxy = { version = "0.1", default-features = false }
# With HTTPS backend support
[dependencies]
tiny-proxy = { version = "0.1", default-features = false, features = ["tls"] }
# With management API
[dependencies]
tiny-proxy = { version = "0.1", default-features = false, features = ["tls", "api"] }
# Full standalone (same as default)
[dependencies]
tiny-proxy = { version = "0.1" }Enable CLI dependencies and tiny-proxy binary.
Enable HTTPS backend support using hyper-rustls (pure Rust TLS).
Management API for runtime configuration:
use tiny_proxy::api;
use std::sync::Arc;
use tokio::sync::RwLock;
let config = Arc::new(RwLock::new(Config::from_file("config.caddy")?));
api::start_api_server("127.0.0.1:8081", config).await?;See the module documentation for detailed API reference.
Config- Configuration containerProxy- Proxy instanceDirective- Configuration directivesSiteConfig- Per-site configuration
Config::from_file(path)- Load configuration from fileConfig::from_str(content)- Parse configuration from stringProxy::new(config)- Create proxy instanceProxy::start(addr)- Start proxy serverProxy::config()- Get current configurationProxy::update_config(config)- Update configuration
Run all tests:
cargo testRun specific test types:
# Unit tests only
cargo test --lib
# Integration tests only
cargo test --tests
# Specific test
cargo test test_pattern_matchingRun tests with logging:
RUST_LOG=debug cargo testRun benchmarks:
cargo benchRun specific benchmark:
cargo bench -- benchmark_nametiny-proxy/
├── src/
│ ├── main.rs # CLI entry point
│ ├── lib.rs # Library entry point
│ ├── cli/ # CLI module
│ ├── config/ # Configuration parsing
│ ├── proxy/ # Proxy logic
│ ├── auth/ # Authentication (optional)
│ └── api/ # Management API (optional)
├── examples/ # Usage examples
├── tests/ # Integration tests
├── benches/ # Benchmarks
# Default (CLI + TLS + API)
cargo build
# Library only (no CLI dependencies)
cargo build --no-default-features
# Library with HTTPS support
cargo build --no-default-features --features tls
# Library with API for config management
cargo build --no-default-features --features tls,api
# CLI without API
cargo build --no-default-features --features cli,tls# Basic example
cargo run --example basic
# Background execution
cargo run --example background- ✅ Library mode
- ✅ CLI mode
- ✅ Configuration parsing
- ✅ Reverse proxy
- ✅ Path-based routing
- ✅ Header manipulation
- ✅ URI rewriting
- ✅ Method-based routing
- ✅ Direct responses
- ✅ Authentication module (basic)
- ✅ Management API (basic)
- ⏳ Static file serving
- ⏳ Try files (SPA support)
- ⏳ Timeout configurations
- ⏳ Buffering control
- ⏳ TLS/SSL support
- ⏳ WebSocket support
- ⏳ Rate limiting
- ⏳ Request/response logging
- ⏳ Metrics and monitoring
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Run
cargo testandcargo clippy - Submit a pull request
See LICENSE file.