Foxy 🦊
A minimal, configuration-driven, hyper-extensible Rust HTTP proxy library.
Use Cases
Foxy is ideal for:
- API Gateway: Centralize routing, security, and observability for your microservices.
- Edge Proxy: Secure and control traffic at the edge of your network.
- Backend for Frontend (BFF): Tailor API responses for specific client applications.
- Protocol Translation: Transform requests and responses between different protocols.
- Load Balancing: Distribute incoming traffic across multiple upstream services.
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
- 📝 Structured Logging: JSON logging with trace IDs for better observability
- 🚀 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:
[]
= "..."
Build an instance and start the server:
use Foxy;
// Create a new Foxy instance with layered configuration
let foxy = loader
.with_env_vars // Environment variables (highest priority)
.with_config_file // File-based config (medium priority)
.with_config_file // Defaults (lowest priority)
.build.await?;
// Start the proxy server and wait for it to complete
foxy.start.await?;
Run the Example
Building from Source
Foxy uses platform-specific TLS backends to optimize for different build environments and avoid dependency issues.
Prerequisites
- Rust 1.70+
- Platform-specific TLS dependencies handled automatically
Build
TLS Backend Strategy
- Windows: Uses
rustls-tls(pure Rust) to avoid OpenSSL build issues completely - Unix/Linux: Uses
native-tlswith vendored OpenSSL for Docker builds - Docker: Vendored SSL eliminates build-time dependency issues - no need to install OpenSSL at build time
- Cross-compilation: Platform detection ensures correct TLS backend automatically
Run with Docker
Prerequisites: Docker 20.10+ installed
Pull the multi-arch image:
Run the proxy, exposing port 8080:
Using a Custom Configuration
- Create a
config.jsonfile on your host - Ensure your configuration binds to address
0.0.0.0 - Mount it into the container:
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:
Tip: When you update
config.json, restart withdocker compose restart foxyto 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 = loader
.with_env_vars // First priority
.with_config_file // Second priority
.build.await?;
Example configuration:
For detailed configuration options, see the Configuration Guide.
Security
Add JWT validation with the OIDC security provider:
This configuration validates all requests against the identity provider, while allowing public access to /health.
Basic Auth Provider
Add Basic Authentication to your proxy:
This configuration enables Basic Authentication for all routes, except those matching /public/* with a GET method.
OpenTelemetry Feature
Enable distributed tracing with OpenTelemetry:
# In your Cargo.toml
[]
= { = "...", = ["opentelemetry"] }
Configure the OpenTelemetry collector in your configuration:
SwaggerUI Feature
Enable the Swagger UI feature:
# In your Cargo.toml
[]
= { = "...", = ["swagger-ui"] }
Configure the OpenAPI schemas to be served on the Swagger UI in your configuration:
Structured Logging
Foxy supports structured JSON logging for better observability in production environments:
Key benefits:
- Trace IDs: Every request gets a unique ID for end-to-end tracking
- JSON Format: Machine-parseable logs for integration with log aggregation systems
- Rich Context: Detailed request information and timing metrics
- Static Fields: Add environment-specific fields to all logs
For detailed configuration options, see the Configuration Guide.
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 highly extensible. You can inject your own custom logic into the proxy pipeline by implementing a few simple traits. This allows you to add custom routing rules, request/response modifications, and authentication mechanisms without forking the project.
The primary extension points are:
Filter: Modify requests and responses.Predicate: Implement custom routing logic.SecurityProvider: Add custom authentication and authorization.
All extension points follow a similar pattern:
- Implement the corresponding trait.
- Register your implementation with Foxy's global registry at startup.
- Use your custom component in the configuration file.
For a detailed guide on adding extension points, see the Extension Guide.
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.
Contributions
We welcome and appreciate contributions to Foxy! Please see our Contribution Guide for details on how to get involved, including our development workflow, code style, and testing procedures.
Contributors
A big thank you to all the individuals who have contributed to Foxy!