Skip to content

A minimal, configuration-driven, hyper-extensible HTTP proxy library written in Rust.

License

Notifications You must be signed in to change notification settings

johan-steffens/foxy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

94 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Foxy 🦊

CI-Crate CI-Docker Crates.io Version Crates.io Downloads Rust Version Docker Version Docker Pulls License

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
  • πŸš€ 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

  1. Create a config.json file on your host
  2. Ensure your configuration binds to address 0.0.0.0
  3. 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 with docker 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.

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

License

This project is licensed under the Mozilla Public License Version 2.0.

About

A minimal, configuration-driven, hyper-extensible HTTP proxy library written in Rust.

Resources

License

Stars

Watchers

Forks

Packages

No packages published