HTTP proxy with conditional logging and request control
At a previous company there was an external API we integrated with. Its versioning strategy was somewhat aggressive and we would incur penalties for accessing deprecated API versions. The idea for logprox was born out of that restriction. Old API calls (sometimes saved on someone's machine, test calls, etc) would potentially put the company at risk. If all calls were proxied through a logging mechanism, not only could we determine where the deprecated calls were coming from, we could block those calls entirely.
# Build from source
git clone https://github.com/bryan-lott/logprox.git
cd logprox
cargo build --release# Start with default config
./target/release/logprox
# Specify custom config
./target/release/logprox --config my-config.yaml
# Set environment variables
PORT=8080 CONFIG_FILE=config.yaml ./target/release/logproxCreate config.yaml:
logging:
default: false
rules:
- name: "Monitor API calls"
match_conditions:
path:
patterns: ["/api/.*"]
capture:
method: true
path: true
timing: trueStart LogProx and test:
# Proxy format: http://host:port/https://upstream-domain/path
curl -X GET "http://localhost:3000/https://httpbin.org/api/test"- Conditional Logging: Log requests based on path, method, headers, body
- Request Control: Drop requests based on configurable rules
- Hot Reload: Update configuration without restarting
- Built-in Monitoring: Health checks and configuration endpoints
┌─────────────┐ ┌───────────┐ ┌────────────────┐
│ Client │───▶│ LogProx │───▶│ Upstream API │
│ Application │ │ │ │ │
└─────────────┘ └───────────┘ └────────────────┘
│
▼
┌────────────┐
│ Logs & │
│ Metrics │
└────────────┘
LogProx uses YAML configuration with environment variable support (${VAR_NAME}).
| Variable | Default | Description |
|---|---|---|
PORT |
3000 |
Server port |
CONFIG_FILE |
config.yaml |
Configuration file path |
logging:
default: false
rules:
- name: "API Monitoring"
match_conditions:
path: { patterns: ["/api/.*"] }
methods: ["POST", "PUT"]
capture: { method: true, path: true, timing: true }
drop:
default: false
rules:
- name: "Block Bots"
match_conditions:
headers: { "user-agent": ".*bot.*" }
response: { status_code: 403, body: "Access denied" }
response_logging:
default: false
rules:
- name: "Log Errors"
match_conditions:
status_codes: [400, 401, 403, 404, 500, 502, 503]
capture: { status_code: true, timing: true }Proxy requests use URL path encoding:
http://localhost:3000/https://api.example.com/users/123
↑
Encoded upstream URL
Regex Examples:
.*- Match any characters^/api/- Match paths starting with /api/\d+- Match one or more digits(option1|option2)- Match either option
Matching Logic:
- Path patterns: At least one must match
- Methods: Must be in methods list (if specified)
- Headers: All specified headers must match
- Body patterns: At least one must match
- Rule evaluation: First match wins
| Endpoint | Method | Response |
|---|---|---|
/health |
GET | 200 OK with body "OK" |
/config |
GET | Current JSON configuration |
/config/docs |
GET | Configuration documentation |
/config/reload |
POST | Reload configuration |
# Health check
curl http://localhost:3000/health
# Get current config
curl http://localhost:3000/config | jq .
# Reload configuration
curl -X POST http://localhost:3000/config/reload
# View documentation
curl http://localhost:3000/config/docs# Validate YAML syntax
yamllint config.yaml
# Enable debug logging
RUST_LOG=debug ./target/release/logprox- Invalid proxy format: Use
/https://domain/pathformat - Regex errors: Test patterns with regex debugger
- Permission denied: Check config file permissions
| Metric | Time |
|---|---|
| Average proxy overhead | ~3ms |
| Direct upstream (local) | 22ms |
| Proxied request (local) | 25ms |
# Micro-benchmarks
cargo bench --bench performance_microbenchmarks
# Comprehensive benchmarks
cargo bench --bench comprehensive_performance| Operation | Time |
|---|---|
| Cached regex lookup | 10-27 ns |
| Header iteration (6 headers) | 15 ns |
| Config lock (single) | 14 ns |
| String operations (optimized) | 17 ns |
| YAML config parsing | 10 µs |
GNU GPLv3 © Bryan Lott