warpdrive-proxy 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +513 -0
  4. data/bin/warpdrive +27 -0
  5. metadata +52 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7f41e11a5a927aa9ca25a2d9854a7459ffd5ab804655856851a621c888bfe62b
4
+ data.tar.gz: d236c7e2fa49cad6d7b1e27a7518f4dc497f946f805cfc31fe28f736c2a41902
5
+ SHA512:
6
+ metadata.gz: 1bfeb5e2b5d75436218f7cbe9952def586fd6195466bd62982d8eaf139c265aff5d9369216a6ef5fb6058e3f06a7901e117a07394dc95f4b9c89e8b271fafcc0
7
+ data.tar.gz: 950754c8ec4db85df8afd5dab93637bf2dde8c177acfa3c812e70e34b721c352fa0997f1acc2db23d6c047da6ba3192125e01c1c473c7a339507070868693ab9
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Abdelkader Boudih
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,513 @@
1
+ # WarpDrive
2
+
3
+ WarpDrive [shah-wahr-muh] is a high-performance reverse proxy built on [Pingora](https://github.com/cloudflare/pingora) (Cloudflare's Rust proxy framework). We built it because Cloudflare already gave us the Engine — no need to reinvent the wheel in space. It routes traffic to multiple upstream services with protocol awareness, load balancing, and path transformation.
4
+
5
+ ## Features
6
+
7
+ **Routing & Load Balancing:**
8
+ - Multi-upstream routing with path, host, method, and header matching
9
+ - Built-in load balancing (always uses Pingora's LoadBalancer, even for single backends)
10
+ - Path transformation (strip_prefix, rewrite)
11
+ - Protocol support: HTTP, HTTPS, WebSocket (ws/wss), gRPC
12
+ - Unix domain socket support (~30% faster than TCP)
13
+
14
+ **Middleware Chain:**
15
+ - **Direct static file serving** (bypasses backend, 600+ req/s)
16
+ - X-Forwarded-* header management
17
+ - Request/response logging with Prometheus metrics
18
+ - X-Sendfile support (backend-controlled file serving)
19
+ - Gzip compression (including pre-compressed .gz files)
20
+ - Per-IP rate limiting (GCRA token bucket)
21
+ - Circuit breaker (automatic failure detection)
22
+ - Concurrency limiting (max concurrent requests)
23
+ - Custom middleware extensibility
24
+
25
+ **Caching & Coordination:**
26
+ - **L1 Cache**: In-memory LRU (64MB default, probabilistic eviction, won't kill your Raspberry Pi)
27
+ - **L2 Cache**: Redis distributed cache (optional, auto-fallback to L1 on errors)
28
+ - **Invalidation**: PostgreSQL LISTEN/NOTIFY for cross-instance coordination
29
+ - **Graceful Degradation**: Works without Redis/PostgreSQL (memory-only mode)
30
+
31
+ **Observability:**
32
+ - **Prometheus Metrics**: HTTP requests, cache hits/misses, circuit breaker state
33
+ - **Structured Logging**: tracing-based logs with request context
34
+ - **Metrics Endpoint**: `/metrics` on configurable port (default 9090)
35
+
36
+ **Operations:**
37
+ - Two modes: Simple (env vars) or Advanced (TOML routing config)
38
+ - Process supervisor for Ruby/Node/Python upstreams
39
+ - Docker support with Ruby 3.4 Alpine base
40
+ - Environment-based configuration with sensible defaults
41
+ - Graceful shutdown with configurable timeout
42
+
43
+ ## Getting Started
44
+
45
+ ### Prerequisites
46
+
47
+ - **Unix-based OS** (Linux/macOS/FreeBSD/etc) — Windows not supported (at Wrap speed, Windows will break and cause hull breach)
48
+ - Rust 1.90+
49
+ - Optional: Redis, PostgreSQL (for caching/coordination)
50
+
51
+ ### Quick Start
52
+
53
+ **Simple Mode** (single upstream):
54
+ ```bash
55
+ cargo build --release
56
+ WARPDRIVE_TARGET_PORT=3001 WARPDRIVE_HTTP_PORT=8080 ./target/release/warpdrive
57
+ ```
58
+
59
+ **Advanced Mode** (multi-upstream routing):
60
+ ```bash
61
+ # Create config.toml
62
+ cat > config.toml << 'EOF'
63
+ [upstreams.rails]
64
+ protocol = "http"
65
+ host = "127.0.0.1"
66
+ port = 3000
67
+
68
+ [upstreams.cable]
69
+ protocol = "ws"
70
+ socket = "/tmp/cable.sock"
71
+
72
+ [[routes]]
73
+ path_prefix = "/cable"
74
+ upstream = "cable"
75
+
76
+ [[routes]]
77
+ path_prefix = "/"
78
+ upstream = "rails"
79
+ EOF
80
+
81
+ # Run with TOML config
82
+ WARPDRIVE_CONFIG=config.toml ./target/release/warpdrive
83
+ ```
84
+
85
+ ### Configuration
86
+
87
+ **Simple Mode** (env vars only):
88
+
89
+ *Basic Proxy:*
90
+ - `WARPDRIVE_TARGET_HOST=127.0.0.1` — upstream host
91
+ - `WARPDRIVE_TARGET_PORT=3000` — upstream port
92
+ - `WARPDRIVE_HTTP_PORT=80` — HTTP listener port
93
+ - `WARPDRIVE_HTTPS_PORT=443` — HTTPS listener port
94
+
95
+ *Static File Serving:*
96
+ - `WARPDRIVE_STATIC_ENABLED=true` — enable direct static file serving (default: true)
97
+ - `WARPDRIVE_STATIC_ROOT=./public` — static files directory (default: ./public)
98
+ - `WARPDRIVE_STATIC_PATHS=/assets,/packs` — URL paths to serve statically
99
+ - `WARPDRIVE_STATIC_CACHE_CONTROL="..."` — cache header for static files
100
+
101
+ *Caching (Optional):*
102
+ - `WARPDRIVE_CACHE_SIZE=67108864` — memory cache size in bytes (default 64MB)
103
+ - `WARPDRIVE_MAX_CACHE_ITEM_SIZE=1048576` — max item size in bytes (default 1MB)
104
+ - `WARPDRIVE_REDIS_URL=redis://localhost:6379` — Redis L2 cache (optional)
105
+ - `WARPDRIVE_DATABASE_URL=postgresql://localhost/warpdrive` — PostgreSQL for invalidation (optional)
106
+
107
+ *Observability:*
108
+ - `WARPDRIVE_METRICS_ENABLED=true` — enable Prometheus metrics endpoint
109
+ - `WARPDRIVE_METRICS_PORT=9090` — metrics HTTP server port
110
+ - `WARPDRIVE_LOG_LEVEL=info` — log level (error, warn, info, debug)
111
+
112
+ *Resilience:*
113
+ - `WARPDRIVE_RATE_LIMIT_ENABLED=true` — enable per-IP rate limiting
114
+ - `WARPDRIVE_RATE_LIMIT_RPS=100` — requests per second per IP
115
+ - `WARPDRIVE_RATE_LIMIT_BURST=200` — burst size (tokens)
116
+ - `WARPDRIVE_CIRCUIT_BREAKER_ENABLED=true` — enable circuit breaker
117
+ - `WARPDRIVE_CIRCUIT_BREAKER_FAILURE_THRESHOLD=5` — failures before opening
118
+ - `WARPDRIVE_CIRCUIT_BREAKER_TIMEOUT_SECS=60` — seconds before trying half-open
119
+ - `WARPDRIVE_MAX_CONCURRENT_REQUESTS=0` — max concurrent requests (0 = unlimited)
120
+
121
+ *Process Supervision:*
122
+ - `WARPDRIVE_UPSTREAM_COMMAND=bundle exec puma` — command to spawn upstream
123
+ - `WARPDRIVE_UPSTREAM_ARGS=-p 3000` — arguments for upstream command
124
+
125
+ **Advanced Mode** (TOML config):
126
+ - `WARPDRIVE_CONFIG=/path/to/config.toml` — routing configuration
127
+
128
+ See `config.example.toml` for full TOML examples with:
129
+ - Path transformation (strip_prefix, rewrite)
130
+ - Load-balanced pools
131
+ - WebSocket/gRPC routing
132
+ - Unix domain sockets
133
+
134
+ **Deployment Modes:**
135
+
136
+ ```bash
137
+ # Mode 1: Memory-only (dev)
138
+ WARPDRIVE_TARGET_PORT=3000 ./warpdrive
139
+
140
+ # Mode 2: + Redis cache (staging)
141
+ WARPDRIVE_REDIS_URL=redis://localhost:6379 \
142
+ WARPDRIVE_TARGET_PORT=3000 ./warpdrive
143
+
144
+ # Mode 3: Full distributed (production)
145
+ WARPDRIVE_REDIS_URL=redis://localhost:6379 \
146
+ WARPDRIVE_DATABASE_URL=postgresql://localhost/warpdrive \
147
+ WARPDRIVE_METRICS_ENABLED=true \
148
+ WARPDRIVE_RATE_LIMIT_ENABLED=true \
149
+ WARPDRIVE_CIRCUIT_BREAKER_ENABLED=true \
150
+ WARPDRIVE_TARGET_PORT=3000 ./warpdrive
151
+ ```
152
+
153
+ ### Static File Serving
154
+
155
+ WarpDrive can serve static files directly from disk, bypassing your application backend entirely. This is significantly faster than X-Sendfile.
156
+
157
+ **Key Differences:**
158
+ - **Direct Static Serving**: WarpDrive serves files from configured paths (e.g., `/assets/*`) without touching the backend
159
+ - **X-Sendfile**: Backend returns `X-Sendfile` header, then WarpDrive serves the file
160
+ - **Performance**: Static serving is 10-100x faster than backend serving, ideal for assets/images/fonts
161
+
162
+ **Basic Setup:**
163
+ ```bash
164
+ # Serve files from ./public directory
165
+ WARPDRIVE_STATIC_ENABLED=true \
166
+ WARPDRIVE_STATIC_ROOT=./public \
167
+ WARPDRIVE_STATIC_PATHS=/assets,/packs,/images,/favicon.ico \
168
+ ./warpdrive
169
+ ```
170
+
171
+ **Directory Structure:**
172
+ ```
173
+ ./public/
174
+ ├── assets/
175
+ │ ├── application.css
176
+ │ └── application.js
177
+ ├── images/
178
+ │ ├── logo.png
179
+ │ └── hero.jpg
180
+ └── favicon.ico
181
+ ```
182
+
183
+ **URL Mapping:**
184
+ - `GET /assets/application.js` → `./public/assets/application.js`
185
+ - `GET /images/logo.png` → `./public/images/logo.png`
186
+ - `GET /favicon.ico` → `./public/favicon.ico`
187
+
188
+ **Features:**
189
+ - **Content-Type Detection**: 28 MIME types (js, css, html, png, svg, woff2, etc.)
190
+ - **ETag Generation**: `"{size}-{mtime_nanos}"` format for cache validation
191
+ - **304 Not Modified**: Automatic `If-None-Match` handling
192
+ - **Gzip Support**: Serves `.gz` files when `Accept-Encoding: gzip` present
193
+ - **Directory Indexes**: Serves `index.html` for directory requests
194
+ - **Security**: Directory traversal prevention, hidden file blocking
195
+ - **Fallthrough**: Continues to backend if file not found (configurable)
196
+
197
+ **Environment Variables:**
198
+ ```bash
199
+ WARPDRIVE_STATIC_ENABLED=true # Enable/disable (default: true)
200
+ WARPDRIVE_STATIC_ROOT=./public # Root directory (default: ./public)
201
+ WARPDRIVE_STATIC_PATHS=/assets,/packs # URL prefixes (default: /assets,/packs,/images,/favicon.ico)
202
+ WARPDRIVE_STATIC_CACHE_CONTROL="public, max-age=31536000, immutable" # Cache header
203
+ WARPDRIVE_STATIC_GZIP=true # Serve .gz files (default: true)
204
+ WARPDRIVE_STATIC_INDEX_FILES=index.html # Directory indexes (default: index.html)
205
+ WARPDRIVE_STATIC_FALLTHROUGH=true # Pass to backend if not found (default: true)
206
+ ```
207
+
208
+ **Example Responses:**
209
+ ```bash
210
+ # JavaScript with ETag and caching
211
+ $ curl -I http://localhost/assets/app.js
212
+ HTTP/1.1 200 OK
213
+ Content-Type: application/javascript
214
+ Content-Length: 1024
215
+ Cache-Control: public, max-age=31536000, immutable
216
+ ETag: "1024-1759606090065974032"
217
+
218
+ # 304 Not Modified on subsequent request
219
+ $ curl -I -H 'If-None-Match: "1024-1759606090065974032"' http://localhost/assets/app.js
220
+ HTTP/1.1 304 Not Modified
221
+ ETag: "1024-1759606090065974032"
222
+ Cache-Control: public, max-age=31536000, immutable
223
+ ```
224
+
225
+ **Performance:**
226
+ - **Sequential**: ~100 req/s (single curl loop)
227
+ - **Concurrent**: 600+ req/s (500 parallel requests)
228
+ - **Latency**: Sub-millisecond for cached files
229
+ - **No backend overhead**: Rails/app server never touched
230
+
231
+ **Production Tips:**
232
+ - Use CDN for hot assets (CloudFlare, Fastly) for global distribution
233
+ - Enable gzip pre-compression: `gzip -k public/assets/*.{js,css}`
234
+ - Set long cache TTL: files are immutable with content hashing
235
+ - Monitor with Prometheus: `static_files_served_total` metric (future)
236
+
237
+ ### TLS & ACME Configuration
238
+
239
+ WarpDrive supports TLS/HTTPS in three ways:
240
+
241
+ **1. Manual Certificates** (self-signed or custom):
242
+ ```bash
243
+ # Self-signed certificate (development)
244
+ openssl req -x509 -newkey rsa:4096 -nodes \
245
+ -keyout server.key -out server.crt -days 365 \
246
+ -subj "/CN=localhost"
247
+
248
+ WARPDRIVE_TLS_CERT_PATH=server.crt \
249
+ WARPDRIVE_TLS_KEY_PATH=server.key \
250
+ WARPDRIVE_HTTPS_PORT=443 \
251
+ ./warpdrive
252
+ ```
253
+
254
+ **2. ACME/Let's Encrypt** (automatic certificates):
255
+ ```bash
256
+ # Production with automatic Let's Encrypt certificates
257
+ WARPDRIVE_TLS_DOMAINS=example.com,www.example.com \
258
+ WARPDRIVE_STORAGE_PATH=/var/lib/warpdrive \
259
+ WARPDRIVE_HTTP_PORT=80 \
260
+ WARPDRIVE_HTTPS_PORT=443 \
261
+ ./warpdrive
262
+ ```
263
+
264
+ **Environment Variables:**
265
+ - `WARPDRIVE_TLS_DOMAINS=domain1.com,domain2.com` — domains for ACME certificates
266
+ - `WARPDRIVE_STORAGE_PATH=/var/lib/warpdrive` — certificate storage directory
267
+ - `WARPDRIVE_ACME_DIRECTORY=https://acme-v02.api.letsencrypt.org/directory` — ACME server URL
268
+ - `WARPDRIVE_EAB_KID=...` — External Account Binding key ID (optional, for some CAs)
269
+ - `WARPDRIVE_EAB_HMAC_KEY=...` — EAB HMAC key (optional)
270
+
271
+ **ACME Workflow:**
272
+ 1. WarpDrive provisions certificates on startup for all `TLS_DOMAINS`
273
+ 2. HTTP-01 challenges handled at `/.well-known/acme-challenge/*`
274
+ 3. Certificates stored in `{STORAGE_PATH}/certs/{domain}.pem`
275
+ 4. Private keys stored with 0600 permissions
276
+ 5. HTTPS listener starts with provisioned certificates
277
+
278
+ **Certificate Storage Layout:**
279
+ ```
280
+ /var/lib/warpdrive/
281
+ ├── account.json # ACME account credentials
282
+ └── certs/
283
+ ├── example.com.pem # Certificate chain
284
+ ├── example.com.key.pem # Private key
285
+ ├── www.example.com.pem
286
+ └── www.example.com.key.pem
287
+ ```
288
+
289
+ **3. Docker with TLS** (self-signed generation):
290
+ ```bash
291
+ # Docker automatically generates self-signed cert at build time
292
+ docker run -p 80:80 -p 443:443 \
293
+ -e WARPDRIVE_TARGET_PORT=3000 \
294
+ warpdrive
295
+ ```
296
+
297
+ **Let's Encrypt Staging** (testing):
298
+ ```bash
299
+ # Use staging server for testing (avoids rate limits)
300
+ WARPDRIVE_TLS_DOMAINS=test.example.com \
301
+ WARPDRIVE_ACME_DIRECTORY=https://acme-staging-v02.api.letsencrypt.org/directory \
302
+ WARPDRIVE_STORAGE_PATH=/tmp/warpdrive \
303
+ ./warpdrive
304
+ ```
305
+
306
+ **Protocol Support:**
307
+ - HTTP/1.1 and HTTP/2 (automatic via ALPN)
308
+ - WebSocket over TLS (wss://)
309
+ - HTTP/3/QUIC (tracked, blocked on Pingora support)
310
+
311
+ ### Docker
312
+
313
+ Run WarpDrive with Puma and Falcon backends:
314
+
315
+ ```bash
316
+ docker-compose up warpdrive
317
+ ```
318
+
319
+ Test routing:
320
+ ```bash
321
+ curl http://localhost:8080/ # → Puma
322
+ curl http://localhost:8080/puma/test # → Puma (/test)
323
+ curl http://localhost:8080/falcon/test # → Falcon (/test)
324
+ ```
325
+
326
+ See `DOCKER.md` for details.
327
+
328
+ ### Tests
329
+
330
+ **Quick Start** (Docker Compose with PostgreSQL and Redis):
331
+ ```bash
332
+ # Run all tests in isolated environment
333
+ docker-compose up --build test
334
+ ```
335
+
336
+ **Local Development:**
337
+ ```bash
338
+ # Start services
339
+ docker-compose up -d postgres redis
340
+
341
+ # Run tests
342
+ export WARPDRIVE_DATABASE_URL=postgresql://warpdrive:warpdrive_test@localhost:5432/warpdrive_test
343
+ export WARPDRIVE_REDIS_URL=redis://localhost:6379
344
+ cargo test --workspace --all-features
345
+ ```
346
+
347
+ **Test Categories:**
348
+ ```bash
349
+ # Unit tests only
350
+ cargo test --lib
351
+
352
+ # Integration tests
353
+ cargo test --test '*'
354
+
355
+ # Specific test suites
356
+ cargo test --lib cache
357
+ cargo test --test redis_test
358
+ cargo test --test postgres_test
359
+ ```
360
+
361
+ See [`TESTING.md`](TESTING.md) for comprehensive testing guide including:
362
+ - Docker Compose test setup
363
+ - CI/CD configuration examples
364
+ - Coverage reports
365
+ - Troubleshooting guide
366
+
367
+ ### Environment Variables Reference
368
+
369
+ **Complete list of all configuration options:**
370
+
371
+ ```bash
372
+ # Core Proxy
373
+ WARPDRIVE_TARGET_HOST=127.0.0.1 # Upstream host (simple mode)
374
+ WARPDRIVE_TARGET_PORT=3000 # Upstream port (simple mode)
375
+ WARPDRIVE_HTTP_PORT=80 # HTTP listener port
376
+ WARPDRIVE_HTTPS_PORT=443 # HTTPS listener port
377
+
378
+ # TLS & ACME
379
+ WARPDRIVE_TLS_DOMAINS=example.com,www.example.com # ACME domains (comma-separated)
380
+ WARPDRIVE_TLS_CERT_PATH=/path/to/cert.pem # Manual certificate path
381
+ WARPDRIVE_TLS_KEY_PATH=/path/to/key.pem # Manual key path
382
+ WARPDRIVE_STORAGE_PATH=/var/lib/warpdrive # Certificate storage directory
383
+ WARPDRIVE_ACME_DIRECTORY=https://... # ACME server URL
384
+ WARPDRIVE_EAB_KID=... # External Account Binding key ID
385
+ WARPDRIVE_EAB_HMAC_KEY=... # External Account Binding HMAC key
386
+
387
+ # Caching
388
+ WARPDRIVE_CACHE_SIZE=67108864 # Memory cache size in bytes (64MB)
389
+ WARPDRIVE_MAX_CACHE_ITEM_SIZE=1048576 # Max item size in bytes (1MB)
390
+ WARPDRIVE_REDIS_URL=redis://localhost:6379 # Redis L2 cache (optional)
391
+ WARPDRIVE_DATABASE_URL=postgresql://... # PostgreSQL for invalidation (optional)
392
+
393
+ # Observability
394
+ WARPDRIVE_METRICS_ENABLED=true # Enable Prometheus metrics
395
+ WARPDRIVE_METRICS_PORT=9090 # Metrics server port
396
+ WARPDRIVE_LOG_LEVEL=info # Log level (error/warn/info/debug/trace)
397
+ WARPDRIVE_LOG_REQUESTS=true # Log all HTTP requests
398
+
399
+ # Resilience
400
+ WARPDRIVE_RATE_LIMIT_ENABLED=true # Enable per-IP rate limiting
401
+ WARPDRIVE_RATE_LIMIT_RPS=100 # Requests per second per IP
402
+ WARPDRIVE_RATE_LIMIT_BURST=200 # Burst size (tokens)
403
+ WARPDRIVE_CIRCUIT_BREAKER_ENABLED=true # Enable circuit breaker
404
+ WARPDRIVE_CIRCUIT_BREAKER_FAILURE_THRESHOLD=5 # Failures before opening
405
+ WARPDRIVE_CIRCUIT_BREAKER_TIMEOUT_SECS=60 # Seconds before retry
406
+ WARPDRIVE_MAX_CONCURRENT_REQUESTS=0 # Max concurrent requests (0 = unlimited)
407
+ WARPDRIVE_UPSTREAM_TIMEOUT=30 # Upstream request timeout in seconds
408
+
409
+ # Headers & Middleware
410
+ WARPDRIVE_FORWARD_HEADERS=true # Add X-Forwarded-* headers
411
+ WARPDRIVE_X_SENDFILE_ENABLED=true # Enable X-Sendfile support
412
+ WARPDRIVE_GZIP_COMPRESSION_ENABLED=true # Enable gzip compression
413
+
414
+ # Static File Serving
415
+ WARPDRIVE_STATIC_ENABLED=true # Enable direct static file serving
416
+ WARPDRIVE_STATIC_ROOT=./public # Static files directory
417
+ WARPDRIVE_STATIC_PATHS=/assets,/packs,/images,/favicon.ico # URL paths to serve
418
+ WARPDRIVE_STATIC_CACHE_CONTROL="public, max-age=31536000, immutable" # Cache header
419
+ WARPDRIVE_STATIC_GZIP=true # Serve .gz files when available
420
+ WARPDRIVE_STATIC_INDEX_FILES=index.html # Directory index files
421
+ WARPDRIVE_STATIC_FALLTHROUGH=true # Continue to backend if file not found
422
+
423
+ # Advanced (TOML Mode)
424
+ WARPDRIVE_CONFIG=/path/to/config.toml # TOML routing config
425
+
426
+ # Process Supervision
427
+ WARPDRIVE_UPSTREAM_COMMAND=bundle exec puma # Command to spawn
428
+ WARPDRIVE_UPSTREAM_ARGS=-p 3000 # Command arguments
429
+ ```
430
+
431
+ ### Prometheus Metrics
432
+
433
+ WarpDrive exposes Prometheus metrics at `/metrics` on the configured port (default 9090).
434
+
435
+ **HTTP Metrics:**
436
+ - `http_requests_total{method, status}` — Total HTTP requests (counter)
437
+ - `http_request_duration_seconds{method, status}` — Request duration histogram (0.001s to 60s buckets)
438
+ - `http_requests_active` — Currently active requests (gauge)
439
+
440
+ **Cache Metrics:**
441
+ - `cache_hits_total{backend}` — Cache hits by backend (memory/redis)
442
+ - `cache_misses_total{backend}` — Cache misses by backend
443
+ - `cache_invalidations_total` — PostgreSQL NOTIFY invalidations received
444
+ - `cache_errors_total{backend, operation}` — Cache operation errors
445
+
446
+ **Circuit Breaker Metrics:**
447
+ - `circuit_breaker_state{state}` — Current state (closed/open/half_open) (gauge)
448
+ - `circuit_breaker_failures_total` — Total failures detected
449
+ - `circuit_breaker_state_changes_total{from, to}` — State transitions
450
+
451
+ **Rate Limiting Metrics:**
452
+ - `rate_limit_requests_allowed_total` — Requests allowed through
453
+ - `rate_limit_requests_denied_total` — Requests rate-limited (429 responses)
454
+
455
+ **Example Prometheus Queries:**
456
+ ```promql
457
+ # Request rate by status code
458
+ rate(http_requests_total[5m])
459
+
460
+ # 95th percentile response time
461
+ histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
462
+
463
+ # Cache hit ratio
464
+ sum(rate(cache_hits_total[5m])) / (sum(rate(cache_hits_total[5m])) + sum(rate(cache_misses_total[5m])))
465
+
466
+ # Circuit breaker state (1=open, 0=closed)
467
+ circuit_breaker_state{state="open"}
468
+
469
+ # Rate limit rejection rate
470
+ rate(rate_limit_requests_denied_total[5m])
471
+ ```
472
+
473
+ **Grafana Dashboard:**
474
+ ```json
475
+ {
476
+ "dashboard": {
477
+ "title": "WarpDrive Proxy",
478
+ "panels": [
479
+ {
480
+ "title": "Request Rate",
481
+ "targets": [{"expr": "rate(http_requests_total[5m])"}]
482
+ },
483
+ {
484
+ "title": "Cache Hit Ratio",
485
+ "targets": [{"expr": "sum(rate(cache_hits_total[5m])) / (sum(rate(cache_hits_total[5m])) + sum(rate(cache_misses_total[5m])))"}]
486
+ },
487
+ {
488
+ "title": "Circuit Breaker State",
489
+ "targets": [{"expr": "circuit_breaker_state"}]
490
+ }
491
+ ]
492
+ }
493
+ }
494
+ ```
495
+
496
+ ## Architecture
497
+
498
+ - **Proxy Handler** (`src/proxy/handler.rs`): Pingora ProxyHttp implementation
499
+ - **Router** (`src/router/`): Multi-upstream routing with LoadBalancer
500
+ - **Middleware** (`src/middleware/`): Request/response filtering chain
501
+ - **Cache** (`src/cache/`): L1 (Memory) + L2 (Redis) coordinator with PG invalidation
502
+ - **Metrics** (`src/metrics/`): Prometheus instrumentation
503
+ - **Config** (`src/config/`): Env vars and TOML parsing
504
+ - **Process** (`src/process/`): Upstream supervisor
505
+
506
+ **Documentation:**
507
+ - `docs/ARCHITECTURE.md` — System architecture, request lifecycle, deployment modes
508
+ - `ROUTING.md` — Multi-upstream routing details
509
+ - `MASTER_PLAN.md` — Development roadmap and current status
510
+
511
+ ## License
512
+
513
+ Licensed under the [MIT License](LICENSE).
data/bin/warpdrive ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ abort <<~ERROR
5
+ ❌ WarpDrive binary not available for this platform
6
+
7
+ You installed the stub gem. Please install a platform-specific gem:
8
+
9
+ gem uninstall warpdrive-proxy
10
+ gem install warpdrive-proxy
11
+
12
+ RubyGems will automatically select the correct platform.
13
+
14
+ Supported platforms:
15
+ - macOS (Apple Silicon): arm64-darwin
16
+ - macOS (Intel): x86_64-darwin
17
+ - Linux (x86_64): x86_64-linux
18
+ - FreeBSD (x86_64): x86_64-freebsd
19
+
20
+ Or build from source:
21
+ git clone https://github.com/seuros/warpdrive
22
+ cd warpdrive
23
+ cargo build --release
24
+ sudo cp target/release/warpdrive /usr/local/bin/
25
+
26
+ GitHub: https://github.com/seuros/warpdrive
27
+ ERROR
metadata ADDED
@@ -0,0 +1,52 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: warpdrive-proxy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Seuros
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies: []
12
+ description: "WarpDrive is a high-performance reverse proxy built on Pingora\n(Cloudflare's
13
+ Rust proxy framework). \n\nThis is a stub gem. Install the platform-specific gem
14
+ for your system:\n- gem install warpdrive-proxy (RubyGems will auto-select the right
15
+ platform)\n"
16
+ email:
17
+ - seuros@users.noreply.github.com
18
+ executables:
19
+ - warpdrive
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - LICENSE
24
+ - README.md
25
+ - bin/warpdrive
26
+ homepage: https://github.com/seuros/warpdrive
27
+ licenses:
28
+ - MIT
29
+ metadata:
30
+ homepage_uri: https://github.com/seuros/warpdrive
31
+ source_code_uri: https://github.com/seuros/warpdrive
32
+ changelog_uri: https://github.com/seuros/warpdrive/blob/main/CHANGELOG.md
33
+ bug_tracker_uri: https://github.com/seuros/warpdrive/issues
34
+ documentation_uri: https://github.com/seuros/warpdrive/blob/main/README.md
35
+ rdoc_options: []
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 2.6.0
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ requirements: []
49
+ rubygems_version: 3.6.9
50
+ specification_version: 4
51
+ summary: High-performance reverse proxy built on Cloudflare's Pingora
52
+ test_files: []