30 releases
Uses new Rust 2024
new 0.2.14 | May 21, 2025 |
---|---|
0.2.13 | May 20, 2025 |
0.1.7 | May 2, 2025 |
0.1.0 |
|
0.0.8 | Apr 30, 2025 |
#231 in Web programming
2,648 downloads per month
195KB
3.5K
SLoC
Foxy 🦊
A minimal, configuration-driven, hyper-extensible Rust HTTP proxy library.
Features
- 🛣️ Powerful Routing: Predicate-based routing with path patterns, HTTP methods, headers, and query matching
- 🔄 Flexible Filters: Pre- and post-processing filters for request/response modification
- ⚙️ Configuration Superpowers: Layered configuration from files and environment variables
- 🌐 Fine-grained Control: Route-specific filter chains for precise request handling
- 🔒 Pluggable Security: Configurable authentication with built-in OIDC support
- 📊 Observability: OpenTelemetry integration for distributed tracing
- 🚀 Modern Async Architecture: Built on Tokio and Hyper for high performance
- 📦 Lightweight Dependencies: Minimal external dependencies for core functionality
- 🧩 Highly Extensible: Custom predicates, filters, and security providers via simple traits
- 🚢 Docker Support: Official container image for rapid deployment
Quickstart
As a Library
Add Foxy to your Cargo.toml
:
[dependencies]
foxy-io = "..."
Build an instance and start the server:
use foxy::Foxy;
// Create a new Foxy instance with layered configuration
let foxy = Foxy::loader()
.with_env_vars() // Environment variables (highest priority)
.with_config_file("config.toml") // File-based config (medium priority)
.with_config_file("defaults.toml") // Defaults (lowest priority)
.build().await?;
// Start the proxy server and wait for it to complete
foxy.start().await?;
Run the Example
git clone https://github.com/johan-steffens/foxy.git
cd foxy
export RUST_LOG=debug
export FOXY_CONFIG_FILE=$(pwd)/config/example.json
cargo run --bin foxy
Run with Docker
Prerequisites: Docker 20.10+ installed
Pull the multi-arch image:
docker pull johansteffens/foxy:latest
Run the proxy, exposing port 8080:
docker run --rm -p 8080:8080 johansteffens/foxy:latest
Using a Custom Configuration
- Create a
config.json
file on your host - Ensure your configuration binds to address
0.0.0.0
- Mount it into the container:
docker run --rm -p 8080:8080 \
-v "$(pwd)/config.json:/app/config.json:ro" \
-e FOXY_CONFIG_FILE=/app/config.json \
johansteffens/foxy:latest
Run with Docker Compose
Create a docker-compose.yml
file:
version: "3.9"
services:
foxy:
image: johansteffens/foxy:latest
container_name: foxy
ports:
- "8080:8080"
environment:
FOXY_CONFIG_FILE: /config/config.json
volumes:
- ./config.json:/config/config.json:ro
Start the service:
docker compose up -d
Tip: When you update
config.json
, restart withdocker compose restart foxy
to apply changes.
Core Concepts
Routing System
Foxy uses a predicate-based routing system to determine how requests are handled:
- Predicates: Conditions that match against request properties (path, method, headers, query)
- Priority: Routes with higher priority are evaluated first
- Filters: Processing steps applied to matched routes
Configuration
Foxy's configuration can be provided through multiple sources:
// Build a layered configuration
let foxy = Foxy::loader()
.with_env_vars() // First priority
.with_config_file("config.json") // Second priority
.build().await?;
Example configuration:
{
"routes": [
{
"id": "api-route",
"target": "https://api.example.com",
"filters": [
{
"type": "path_rewrite",
"config": {
"pattern": "^/api/(.*)$",
"replacement": "/v2/$1"
}
}
],
"predicates": [
{
"type_": "path",
"config": {
"pattern": "/api/*"
}
}
]
}
]
}
For detailed configuration options, see the Configuration Guide.
Security
Add JWT validation with the OIDC security provider:
{
"proxy": {
"security_chain": [
{
"type": "oidc",
"config": {
"issuer-uri": "https://id.example.com/.well-known/openid-configuration",
"aud": "my-api",
"bypass-routes": [
{ "methods": ["GET"], "path": "/health" }
]
}
}
]
}
}
This configuration validates all requests against the identity provider, while allowing public access to /health
.
OpenTelemetry Integration
Enable distributed tracing with OpenTelemetry:
# In your Cargo.toml
[dependencies]
foxy-io = { version = "...", features = ["opentelemetry"] }
Configure the OpenTelemetry collector in your configuration:
{
"proxy": {
"opentelemetry": {
"endpoint": "http://otel-collector:4317",
"service_name": "my-proxy-service",
"include_headers": true,
"resource_attributes": {
"host.name": "proxy-pod-abc123"
},
"collector_headers": {
"X-API-Key": "d41000b6-6191-47c5-99f1-7b88b1b97409"
}
}
}
}
Performance Features
Streaming Architecture
- Zero-Copy Streaming: Request and response bodies are streamed end-to-end
- Backpressure Support: Large uploads/downloads propagate backpressure correctly
- Memory Efficiency: Memory usage is bound by socket buffers, not by request/response size
Detailed Metrics
Foxy logs three high-resolution latencies on every call (DEBUG level):
[timing] GET /api/users -> 200 | total=152ms upstream=148ms internal=4ms
Metric | Description |
---|---|
total | Wall-clock time from first byte in to last byte out |
upstream | Time spent awaiting the target server |
internal | Proxy-side processing time (total − upstream ) |
Request and Response Logging
The LoggingFilter
can peek and log request/response bodies:
- Logs the first 1,000 bytes/characters (UTF-8 lossy conversion)
- Safely handles binary or large payloads
- Configurable log level and content limits
Note: Body logging adds some latency to proxied calls.
Extension Points
Foxy is designed to be extended through traits:
- ConfigProvider: Add custom configuration sources
- Filter: Create custom request/response processing logic
- Predicate: Implement custom routing logic
- SecurityProvider: Add authentication mechanisms
Development Status
- Configuration System
- Loader Module
- Core HTTP Proxy
- Predicate-based Routing
- Request/Response Filters
- Security Chain
- OIDC provider
- Basic auth provider
- OpenTelemetry Integration
License
This project is licensed under the Mozilla Public License Version 2.0.
Dependencies
~18–39MB
~668K SLoC