A high-performance, multi-region HTTP and SOAP proxy built with Rust for Cloudflare Workers using Durable Objects. Designed for reliable API forwarding with built-in authorization, intelligent logging, and global distribution.
- ๐ Secure Authorization: Bearer token authentication via Cloudflare Secrets
- ๐ Multi-Region Support: 8 Cloudflare regions with WNAM default
- ๐ Two-Level Logging: Info (production) and debug logging via
X-Log-Levelheader - ๐ Pure Rust: WASM-compiled for maximum performance (~325KB gzip)
- ๐ HTTP Proxy: Support for GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS
- ๐งผ SOAP Support: NuSOAP-compatible SOAP 1.1 via
X-Request-Type: soapheader - โก Edge Performance: Sub-millisecond startup, global deployment with Durable Objects
- ๐ก๏ธ EU Jurisdiction: Location hints ensure GDPR-compliant data residency
- ๐ Smart Logging: Minimal logging (info) by default, detailed logging on demand (debug)
- โฑ๏ธ Automatic Timeout Protection: 30-second timeout enforced by Cloudflare Workers
- ๐ Hash-Based Load Distribution: 10x concurrency via automatic load balancing (80 DOs globally)
I ran into a real-world problem: my server's region was blocked by an API provider I needed to integrate with. Traditional solutions didn't work:
- VPN wasn't practical - I only needed it for specific API calls, not all traffic
- IP whitelisting conflicts - Some of my integrations had strict IP whitelists that wouldn't work with a VPN
- Multiple regional requirements - Different providers needed different regions (some required EU for GDPR, others needed US endpoints)
This proxy solves these problems by:
- Selective routing - Route only specific requests through the proxy, not all traffic
- Multi-region flexibility - Choose the appropriate region per request via headers
- Stable IP addresses - Cloudflare's Durable Objects provide consistent IPs per region
- Zero server maintenance - Runs on Cloudflare's edge network with automatic scaling
- Rust (latest stable)
- Node.js (for Wrangler)
- Cloudflare account
- Wrangler CLI
-
Clone the repository
git clone <your-repo-url> cd api-proxy
-
Install dependencies
npm install -g wrangler cargo install worker-build
-
Login to Cloudflare
wrangler login
-
Configure AUTH_TOKEN
# Generate secure token openssl rand -base64 32 # Set as Cloudflare secret wrangler secret put AUTH_TOKEN # Paste the generated token when prompted
-
Deploy
wrangler deploy
Basic POST Request
curl -X POST https://api-proxy.admice.com/ \
-H "Authorization: Bearer YOUR_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://api.example.com/data",
"method": "post",
"params": {
"key": "value"
}
}'GET Request with Query Parameters
curl -X POST https://api-proxy.admice.com/ \
-H "Authorization: Bearer YOUR_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://api.example.com/users",
"method": "get",
"params": {
"page": "1",
"limit": "10"
}
}'Response Format
{
"status": 200,
"headers": {
"content-type": "application/json"
},
"body": {
"result": "success"
}
}SOAP Request with X-Request-Type Header
curl -X POST https://api-proxy.admice.com/ \
-H "Authorization: Bearer YOUR_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Request-Type: soap" \
-d '{
"url": "https://soap.example.com/service",
"action": "getDIDCountry",
"namespace": "urn:getDIDCountry",
"params": [
["did", "1234567890"],
["country", "US"]
]
}'Control request processing location with the X-CF-Region header.
| Region Code | Description | Location Hint |
|---|---|---|
wnam |
Western North America | US West |
enam |
Eastern North America | US East |
weur |
Western Europe | EU West (GDPR) |
eeur |
Eastern Europe | EU East (GDPR) |
apac |
Asia-Pacific | Asia |
oc |
Oceania | Australia |
af |
Africa | Africa |
me |
Middle East | Middle East |
| Default | (no header) | WNAM |
curl -X POST https://api-proxy.admice.com/ \
-H "Authorization: Bearer YOUR_AUTH_TOKEN" \
-H "X-CF-Region: weur" \
-H "Content-Type: application/json" \
-d '{"url": "https://api.example.com/data", "method": "get"}'Log Output (with debug logging):
[INFO] Request received at datacenter: CDG
[INFO] Selected region: weur
[INFO] WEURProcessor processing in datacenter: CDG (Region: Western Europe)
[INFO] Processing HTTP request
[DEBUG] HTTP method: Get, url: https://api.example.com/data
[INFO] Response status: 200
[INFO] HTTP request completed successfully
Two logging levels controlled via X-Log-Level header.
| Level | Default | What's Logged |
|---|---|---|
info |
โ Yes | Request received, region selected, DO processing location, response status, completion |
debug |
โฌ No | All of the above PLUS: request path, HTTP method, target URL, parameters count, headers count, response body size |
curl -X POST https://api-proxy.admice.com/ \
-H "Authorization: Bearer YOUR_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{"url": "https://httpbin.org/post", "method": "post", "params": {"test": "value"}}'Log Output:
[INFO] Request received at datacenter: LAX
[INFO] Selected region: wnam
[INFO] WNAMProcessor processing in datacenter: LAX (Region: Western North America)
[INFO] Processing HTTP request
[INFO] Response status: 200
[INFO] HTTP request completed successfully
curl -X POST https://api-proxy.admice.com/ \
-H "Authorization: Bearer YOUR_AUTH_TOKEN" \
-H "X-Log-Level: debug" \
-H "Content-Type: application/json" \
-d '{"url": "https://httpbin.org/post", "method": "post", "params": {"test": "value"}}'Log Output:
[INFO] Request received at datacenter: LAX
[DEBUG] Request path: /
[INFO] Selected region: wnam
[INFO] WNAMProcessor processing in datacenter: LAX (Region: Western North America)
[INFO] Processing HTTP request
[DEBUG] HTTP method: Post, url: https://httpbin.org/post
[DEBUG] Sending Post request to https://httpbin.org/post with JSON body
[DEBUG] Request headers: 0 custom headers
[INFO] Response status: 200
[DEBUG] Response headers: 8 headers
[DEBUG] Response body size: 730 bytes
[INFO] HTTP request completed successfully
Cloudflare Workers automatically enforces a 30-second timeout on all fetch requests, protecting against slow or hanging endpoints.
Timeout Behavior:
- Fixed Duration: 30 seconds (enforced by Cloudflare Workers platform)
- Automatic: No configuration needed - built into Workers runtime
- On Timeout: Returns error response indicating timeout
- Production Ready: Prevents resource blocking from unresponsive endpoints
# All requests automatically timeout after 30 seconds
curl -X POST https://api-proxy.admice.com/ \
-H "Authorization: Bearer YOUR_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{"url": "https://httpbin.org/delay/5", "method": "get"}'All requests require a valid AUTH_TOKEN in the Authorization header.
Generate a secure token:
openssl rand -base64 32Set as Cloudflare secret:
wrangler secret put AUTH_TOKEN
# Paste your generated token when promptedUse in requests:
curl -X POST https://api-proxy.admice.com/ \
-H "Authorization: Bearer YOUR_GENERATED_TOKEN" \
...| Status | Condition | Response |
|---|---|---|
200 OK |
Valid request | Proxy response |
403 Forbidden |
Missing or invalid token | "Forbidden" |
{
"url": string, // Target URL (required)
"method": string, // HTTP method: get, post, put, delete, patch, head, options (default: "post")
"params": object, // Query params (GET/HEAD/DELETE) or body params (POST/PUT/PATCH)
"headers": object // Additional headers to forward
}Note: All requests automatically timeout after 30 seconds (Cloudflare Workers limit)
{
"url": string, // SOAP endpoint URL (required)
"action": string, // SOAP action/method name (required)
"namespace": string, // SOAP action namespace (required)
"params": [string, any][], // Array of [key, value] tuples (preserves order)
"headers": object // Additional headers to forward
}Notes:
- Use
X-Request-Type: soapheader to indicate SOAP request - All requests automatically timeout after 30 seconds (Cloudflare Workers limit)
{
"status": number, // HTTP status code (200-299)
"headers": object, // Response headers as key-value pairs
"body": any // Response body (JSON object or string)
}{
"status": number, // HTTP status code (400-599)
"message": string // Error message
}| Header | Required | Default | Description |
|---|---|---|---|
Authorization |
โ Yes | - | Bearer token authentication |
Content-Type |
โ Yes | - | Must be application/json |
X-CF-Region |
โฌ No | wnam |
Target region code |
X-Request-Type |
โฌ No | http |
Set to soap for SOAP requests |
X-Log-Level |
โฌ No | info |
Set to debug for detailed logging |
A comprehensive Postman collection is included for testing and API exploration.
- Import
API_Proxy.postman_collection.jsoninto Postman - Configure collection variables:
{{BASE_URL}}:https://api-proxy.admice.com{{AUTH_TOKEN}}: Your token from Cloudflare secrets{{REGION}}: Desired region (default:wnam)
-
โ Quick Tests (4 requests)
- HTTP GET, POST with parameters
- SOAP request
- Region-specific request
-
๐ Multi-Region Tests (3 requests)
- WNAM, WEUR, APAC with datacenter verification
-
๐ Logging Tests (2 requests)
- Info level (default)
- Debug level (detailed)
-
โ Error Handling (2 requests)
- Invalid authentication
- Target endpoint errors
# Install dependencies
cargo build
# Run local dev server
wrangler dev
# Test locally (use test token for local development)
curl -X POST http://localhost:8787/ \
-H "Authorization: Bearer test-token" \
-H "Content-Type: application/json" \
-d '{"url": "https://httpbin.org/get", "method": "get"}'# Build for production
wrangler build
# Check build output
ls -lh build/We provide a beautiful test script that validates the hash-based load distribution and measures throughput:
# Run comprehensive load distribution test
./scripts/test-load-distribution.shThe script performs:
- Warmup Test: 1 request per region (5 total) - tests cold start behavior
- Heavy Load Test: 100 requests per region (500 total) - validates throughput and distribution
Expected Results (with warm instances):
- โ Success Rate: >99% (499/500 requests typical)
- โก Throughput: ~11-12 req/s with httpbin.org
- ๐ Load Distribution: Automatic routing across 10 DOs per region (50 DOs total for 5 regions)
Sample Output:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ API Proxy Load Distribution Performance Test โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Test: Heavy Load Test (Hot Start)
Regions: wnam enam weur eeur apac
Requests per region: 100
Total concurrent requests: 500
โ Completed in 42.4s
Results:
โ Success: 499/500 (99.8%)
โก Throughput: 11.78 req/s
โฑ Avg latency: 84ms per request
# Watch logs in real-time
wrangler tail --format pretty
# Test with debug logging
curl -X POST https://api-proxy.admice.com/ \
-H "Authorization: Bearer YOUR_AUTH_TOKEN" \
-H "X-Log-Level: debug" \
-H "Content-Type: application/json" \
-d '{"url": "https://httpbin.org/get", "method": "get"}'wrangler deploywrangler secret put AUTH_TOKENwrangler tail --format prettyCloudflare Workers provides built-in Git integration for automatic deployments. This is the easiest way to set up CI/CD for Rust WASM projects:
-
Navigate to Cloudflare Dashboard
- Go to Workers & Pages
- Select your
api-proxyworker - Click Settings โ Deployments
-
Connect Git Repository
- Click "Connect to Git"
- Authorize GitHub/GitLab
- Select repository:
erimeilis/api-proxy - Select branch:
main
-
Configure Build Settings
Since this is a Rust WASM project, the build configuration is not straightforward. Use these exact commands:
Build command:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
Deploy command:
. "$HOME/.cargo/env" && npx wrangler deploy
โ ๏ธ The. "$HOME/.cargo/env" &&prefix is mandatory. The build command and deploy command run in separate shells, so Rust installed during the build step is not onPATHin the deploy step. Without sourcing the cargo env, wrangler's[build]step fails withcargo: not found(exit code 127).To upload a version without promoting it to production (e.g. for non-
mainbranch builds), useversions uploadinstead ofdeployโ keeping the same prefix:. "$HOME/.cargo/env" && npx wrangler versions upload
Root directory:
/(default) -
Environment Variables
- Secrets (like
AUTH_TOKEN) are managed separately via Wrangler CLI - They persist across deployments automatically
- No need to configure in CI/CD settings
- Secrets (like
-
Save and Deploy
- Click "Save and Deploy"
- Every push to
mainwill trigger automatic deployment - Build logs available in real-time during deployment
Why these commands?
- Rust isn't pre-installed in Cloudflare's build environment
- The build command installs Rust using the official rustup installer
- The deploy command sources the Rust environment and runs wrangler
worker-buildis automatically installed by the wrangler build process
โโโโโโโโโโโโโโโโโโโ
โ Client Request โ
โ (with token) โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Main Worker โ
โ โโโโโโโโโโโโโโโโโโโโโ โ
โ โ Authentication โ โ
โ โโโโโโโโโโโฌโโโโโโโโโโ โ
โ โ โ
โ โโโโโโโโโโโผโโโโโโโโโโ โ
โ โ Region Router โ โ โ X-CF-Region header
โ โ (8 regions) โ โ
โ โโโโโโโโโโโฌโโโโโโโโโโ โ
โ โ โ
โ โโโโโโโโโโโผโโโโโโโโโโ โ
โ โ Hash-Based โ โ โ Body hash โ DO selector
โ โ Load Balancer โ โ (0-9 per region)
โ โโโโโโโโโโโฌโโโโโโโโโโ โ
โ โ โ
โ โโโโโโโโโโโผโโโโโโโโโโ โ
โ โ Log Level Setup โ โ โ X-Log-Level header
โ โโโโโโโโโโโฌโโโโโโโโโโ โ
โโโโโโโโโโโโโโผโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโ
โ Durable Object โ
โ (1 of 10 per โ
โ region = 80 total)โ
โ โโโโโโโโโโโโโโโโโโ โ
โ โ Request Type โ โ โ X-Request-Type header
โ โ Routing โ โ
โ โโโโโโโโโฌโโโโโโโโโ โ
โ โโโโโโโโโโโโผโโ HTTP Handler (with timeout)
โ โโโโโโโโโโโโผโโ SOAP Handler (with timeout)
โโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโ
โ Target API โ
โ (HTTP/SOAP) โ
โโโโโโโโโโโโโโโโโโ
The proxy uses automatic load balancing across 10 Durable Objects per region:
- Request Body Hashing: Each request body is hashed using Rust's standard hasher
- DO Selection: Hash value modulo 10 determines which DO instance (0-9) handles the request
- Consistent Routing: Same request body always routes to the same DO (useful for debugging)
- Automatic Scaling: No manual configuration needed - DOs are created on-demand
Capacity per Region: ~10,000 req/s (10 DOs ร ~1,000 req/s each) Global Capacity: ~80,000 req/s (8 regions ร 10,000 req/s each)
- Bundle Size: ~914KB (325KB gzip)
- Cold Start: ~2ms
- Execution: Edge network via Durable Objects
- Concurrent Capacity:
- Per Region: ~10,000 req/s (10 DOs ร ~1,000 req/s each)
- Global: ~80,000 req/s (8 regions ร 10,000 req/s each)
- Load Distribution: Automatic hash-based routing across 80 Durable Objects
- Timeout Protection: 30-second automatic timeout (Cloudflare Workers enforced)
- Logging Overhead: Minimal (info level), ~5% additional for debug level
- AUTH_TOKEN: Stored as Cloudflare secret (encrypted at rest)
- HTTPS Only: All requests over TLS 1.3
- No Data Storage: Stateless proxy, logs only to console
- GDPR Compliant: EU regions (weur/eeur) enforce EU datacenter execution
- Location Hints: Durable Objects placed in specified regions for data residency
This project is licensed under the MIT License - see the LICENSE file for details.
- Built with workers-rs
- Deployed on Cloudflare Workers with Durable Objects
- Designed for reliable, multi-region API proxying with intelligent logging
Made with ๐๐ using Rust and Cloudflare Workers