ninja-reverse-proxy 1.0.0 → 1.0.2
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.
- package/README.md +90 -384
- package/package.json +11 -5
package/README.md
CHANGED
|
@@ -1,27 +1,14 @@
|
|
|
1
1
|
# Ninja Reverse Proxy
|
|
2
2
|
|
|
3
|
-
A production-grade, backend-agnostic **Layer 7 Reverse Proxy** built from scratch in
|
|
3
|
+
A production-grade, backend-agnostic **Layer 7 Reverse Proxy** built from scratch in TypeScript and Node.js.
|
|
4
4
|
|
|
5
|
-
Designed in the same philosophy as
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
Developer → GitHub → Jenkins CI/CD → Docker → Any Backend
|
|
9
|
-
```
|
|
5
|
+
Designed in the same philosophy as Nginx, Traefik, and HAProxy — configure it once, point it at any backend, and it handles everything else.
|
|
10
6
|
|
|
11
7
|
---
|
|
12
8
|
|
|
13
|
-
##
|
|
9
|
+
## Works with any HTTP backend
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
- Express · Fastify · NestJS
|
|
18
|
-
- Django · FastAPI · Flask
|
|
19
|
-
- Spring Boot · Quarkus
|
|
20
|
-
- Go (net/http, Gin, Echo)
|
|
21
|
-
- ASP.NET Core
|
|
22
|
-
- Kubernetes Services
|
|
23
|
-
- Docker Compose services
|
|
24
|
-
- Any service that speaks HTTP
|
|
11
|
+
Express · Fastify · NestJS · Django · FastAPI · Flask · Spring Boot · Go · ASP.NET Core · Kubernetes Services · Docker Compose services · **Any service that speaks HTTP**
|
|
25
12
|
|
|
26
13
|
The proxy never cares what technology runs behind the URLs. You configure upstreams in `config.yaml` and the proxy routes, balances, caches, rate-limits, and health-checks them automatically.
|
|
27
14
|
|
|
@@ -31,447 +18,166 @@ The proxy never cares what technology runs behind the URLs. You configure upstre
|
|
|
31
18
|
|
|
32
19
|
| Feature | Details |
|
|
33
20
|
|---|---|
|
|
34
|
-
|
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
|
|
|
40
|
-
|
|
|
41
|
-
|
|
|
42
|
-
|
|
|
43
|
-
|
|
|
44
|
-
|
|
|
45
|
-
|
|
|
46
|
-
|
|
|
47
|
-
|
|
|
48
|
-
| **Jenkins CI/CD** | Declarative pipeline included |
|
|
49
|
-
| **SonarQube** | `sonar-project.properties` included for static analysis |
|
|
50
|
-
|
|
51
|
-
---
|
|
52
|
-
|
|
53
|
-
## Architecture
|
|
54
|
-
|
|
55
|
-
```
|
|
56
|
-
┌─────────────────────────────────────────────────┐
|
|
57
|
-
│ Ninja Reverse Proxy │
|
|
58
|
-
│ │
|
|
59
|
-
Client ──HTTPS──► │ Master Process │
|
|
60
|
-
│ ├── Rate Limiter (per-IP, per-route) │
|
|
61
|
-
│ ├── Redis Cache (GET responses) │
|
|
62
|
-
│ ├── Load Balancer (round-robin / ip-hash / …) │
|
|
63
|
-
│ ├── Health Checker (every 10s) │
|
|
64
|
-
│ ├── Service Registry │
|
|
65
|
-
│ └── Auto Scaler (optional) │
|
|
66
|
-
│ │
|
|
67
|
-
│ Worker Processes (one per CPU core) │
|
|
68
|
-
│ └── Forward requests via keepAlive TCP │
|
|
69
|
-
└───────────┬─────────────────────────────────────┘
|
|
70
|
-
│
|
|
71
|
-
┌───────────────┼───────────────┐
|
|
72
|
-
▼ ▼ ▼
|
|
73
|
-
backend-a backend-b backend-c
|
|
74
|
-
(Express) (Django) (Spring Boot)
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
### CI/CD Flow
|
|
78
|
-
|
|
79
|
-
```
|
|
80
|
-
Developer
|
|
81
|
-
│ edits code / config
|
|
82
|
-
▼
|
|
83
|
-
GitHub
|
|
84
|
-
▼
|
|
85
|
-
Jenkins (Jenkinsfile)
|
|
86
|
-
├── Setup (npm ci)
|
|
87
|
-
├── Static Analysis — Lint + npm audit (parallel)
|
|
88
|
-
├── Unit Tests
|
|
89
|
-
├── Build Artifact (tsc)
|
|
90
|
-
└── Deploy to Production (main branch, prod env)
|
|
91
|
-
```
|
|
21
|
+
| Cluster Architecture | Master/Worker pattern via Node.js cluster — uses all CPU cores |
|
|
22
|
+
| Round-Robin Load Balancing | Equal request distribution across healthy upstreams |
|
|
23
|
+
| Circuit Breaker | Marks upstreams DOWN after configurable failure threshold |
|
|
24
|
+
| Redis Response Cache | GET response caching with configurable TTL |
|
|
25
|
+
| Per-Route Rate Limiting | Sliding window rate limiter per client IP per route |
|
|
26
|
+
| Service Registry | Backends self-register, deregister, and send heartbeats |
|
|
27
|
+
| Continuous Health Checks | Every 10 seconds — auto-removes and auto-recovers upstreams |
|
|
28
|
+
| HTTPS / TLS Termination | Full SSL at the proxy; all HTTP auto-redirected (301) |
|
|
29
|
+
| Sticky Sessions | Cookie-based session affinity per upstream |
|
|
30
|
+
| Retry Logic | Up to 2 retries on upstream failure, each on a different upstream |
|
|
31
|
+
| Graceful Shutdown | Drains all connections on SIGTERM / SIGINT |
|
|
32
|
+
| Hot Reload | Watches `config.yaml` and `config.d/` — zero-downtime config updates |
|
|
33
|
+
| Admin API | Live stats for load balancer, cache, registry, auto scaler |
|
|
34
|
+
| YAML Configuration | One file, fully validated with Zod — no source code changes needed |
|
|
92
35
|
|
|
93
36
|
---
|
|
94
37
|
|
|
95
38
|
## Quick Start
|
|
96
39
|
|
|
97
|
-
### 1.
|
|
40
|
+
### 1. Install globally
|
|
98
41
|
|
|
99
42
|
```bash
|
|
100
|
-
|
|
101
|
-
cd reverse-proxy
|
|
102
|
-
|
|
103
|
-
# Generate a self-signed certificate (for development)
|
|
104
|
-
openssl req -x509 -newkey rsa:4096 \
|
|
105
|
-
-keyout key.pem -out cert.pem \
|
|
106
|
-
-days 365 -nodes
|
|
43
|
+
npm install -g ninja-reverse-proxy
|
|
107
44
|
```
|
|
108
45
|
|
|
109
|
-
### 2.
|
|
46
|
+
### 2. Generate TLS certificates
|
|
110
47
|
|
|
111
48
|
```bash
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
```yaml
|
|
118
|
-
upstreams:
|
|
119
|
-
- id: my-api
|
|
120
|
-
url: http://my-api:8000
|
|
121
|
-
|
|
122
|
-
- id: my-frontend
|
|
123
|
-
url: http://my-frontend:3000
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
### 3. Run
|
|
127
|
-
|
|
128
|
-
```bash
|
|
129
|
-
# Proxy + Redis only (you bring your own backends)
|
|
130
|
-
docker-compose up --build
|
|
131
|
-
|
|
132
|
-
# Or run the built-in demo (backend-a + backend-b included)
|
|
133
|
-
cd examples/docker-compose && docker-compose up --build
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
### 4. Test
|
|
137
|
-
|
|
138
|
-
```bash
|
|
139
|
-
curl -k https://localhost:8443/
|
|
140
|
-
curl -k https://localhost:8443/__lb-stats
|
|
141
|
-
curl -k https://localhost:8443/__registry
|
|
49
|
+
openssl req -x509 -newkey rsa:4096 \
|
|
50
|
+
-keyout key.pem -out cert.pem \
|
|
51
|
+
-days 365 -nodes \
|
|
52
|
+
-subj "/CN=localhost"
|
|
142
53
|
```
|
|
143
54
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
## Configuration Reference
|
|
147
|
-
|
|
148
|
-
`config.example.yaml` is the fully commented template. Copy it to `config.yaml` to get started.
|
|
55
|
+
### 3. Create your config file
|
|
149
56
|
|
|
150
57
|
```yaml
|
|
58
|
+
# config.yaml
|
|
151
59
|
server:
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
workers: 2 # Set to your CPU core count (run: nproc)
|
|
60
|
+
listen: 8080
|
|
61
|
+
httpsPort: 8443
|
|
62
|
+
workers: 2
|
|
156
63
|
|
|
157
64
|
loadBalancing:
|
|
158
|
-
strategy: round-robin
|
|
159
|
-
failureThreshold: 3
|
|
160
|
-
recoveryTimeMs: 15000
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
# true → dynamic server spawning based on load
|
|
165
|
-
minServers: 2
|
|
166
|
-
maxServers: 10
|
|
167
|
-
scaleUpAt: 10 # Spawn a server when connections exceed this
|
|
168
|
-
scaleDownAt: 2 # Kill a server when connections drop below this
|
|
169
|
-
cooldownMs: 60000
|
|
170
|
-
startPort: 9000
|
|
171
|
-
proxyPort: 8080
|
|
172
|
-
|
|
173
|
-
cache:
|
|
174
|
-
enabled: false # true → cache GET responses in Redis
|
|
175
|
-
host: redis
|
|
176
|
-
port: 6379
|
|
177
|
-
ttlSeconds: 60
|
|
65
|
+
strategy: round-robin
|
|
66
|
+
failureThreshold: 3
|
|
67
|
+
recoveryTimeMs: 15000
|
|
68
|
+
retry:
|
|
69
|
+
maxAttempts: 2
|
|
70
|
+
statusCodes: [502, 503, 504]
|
|
178
71
|
|
|
179
72
|
upstreams:
|
|
180
|
-
- id:
|
|
181
|
-
url: http://
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
url: http://backend-b:3002
|
|
73
|
+
- id: my-api
|
|
74
|
+
url: http://localhost:5000
|
|
75
|
+
- id: my-api-2
|
|
76
|
+
url: http://localhost:5001
|
|
185
77
|
|
|
186
78
|
paths:
|
|
187
|
-
- path: /
|
|
188
|
-
upstream:
|
|
189
|
-
- backend-a
|
|
190
|
-
- backend-b
|
|
191
|
-
rateLimit:
|
|
192
|
-
windowMs: 60000 # 1-minute window
|
|
193
|
-
maxRequests: 100000 # per client IP
|
|
194
|
-
|
|
195
|
-
- path: /api # Route /api to a specific backend only
|
|
196
|
-
upstream:
|
|
197
|
-
- backend-a
|
|
79
|
+
- path: /
|
|
80
|
+
upstream: [my-api, my-api-2]
|
|
198
81
|
|
|
199
82
|
headers:
|
|
200
83
|
- key: X-Forwarded-For
|
|
201
84
|
value: client_ip
|
|
202
|
-
- key: X-Real-IP
|
|
203
|
-
value: client_ip
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
---
|
|
207
|
-
|
|
208
|
-
## Docker
|
|
209
85
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
86
|
+
cache:
|
|
87
|
+
enabled: false
|
|
88
|
+
host: redis
|
|
89
|
+
port: 6379
|
|
90
|
+
ttlSeconds: 60
|
|
214
91
|
```
|
|
215
92
|
|
|
216
|
-
###
|
|
93
|
+
### 4. Start the proxy
|
|
217
94
|
|
|
218
95
|
```bash
|
|
219
|
-
|
|
220
|
-
docker-compose up --build
|
|
96
|
+
ninja-proxy --config config.yaml
|
|
221
97
|
```
|
|
222
98
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
### Run the full built-in demo
|
|
99
|
+
### 5. Test it
|
|
226
100
|
|
|
227
101
|
```bash
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
docker-compose up --build
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
### Connect your real app
|
|
234
|
-
|
|
235
|
-
Add your app as a service in your own `docker-compose.yml` and connect it to the proxy network:
|
|
236
|
-
|
|
237
|
-
```yaml
|
|
238
|
-
services:
|
|
239
|
-
|
|
240
|
-
my-express-app:
|
|
241
|
-
image: my-express-app:latest
|
|
242
|
-
networks:
|
|
243
|
-
- proxy-network
|
|
244
|
-
|
|
245
|
-
networks:
|
|
246
|
-
proxy-network:
|
|
247
|
-
external: true
|
|
248
|
-
name: reverse-proxy_proxy-network
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
Then add it to `config.yaml`:
|
|
252
|
-
|
|
253
|
-
```yaml
|
|
254
|
-
upstreams:
|
|
255
|
-
- id: my-express-app
|
|
256
|
-
url: http://my-express-app:3000
|
|
102
|
+
curl -k https://localhost:8443/
|
|
103
|
+
curl -k https://localhost:8443/__lb-stats
|
|
257
104
|
```
|
|
258
105
|
|
|
259
106
|
---
|
|
260
107
|
|
|
261
|
-
##
|
|
262
|
-
|
|
263
|
-
See [`k8s/README.md`](k8s/README.md) for the full deployment guide.
|
|
108
|
+
## Dynamic Service Registry
|
|
264
109
|
|
|
265
|
-
|
|
110
|
+
Backends can self-register at runtime without touching `config.yaml`:
|
|
266
111
|
|
|
267
112
|
```bash
|
|
268
|
-
#
|
|
269
|
-
|
|
113
|
+
# Register a new upstream dynamically
|
|
114
|
+
curl -X POST -H "Content-Type: application/json" \
|
|
115
|
+
-d '{"id":"my-service","url":"http://localhost:3000"}' \
|
|
116
|
+
http://localhost:8080/__registry/register
|
|
270
117
|
|
|
271
|
-
#
|
|
272
|
-
|
|
118
|
+
# Send a heartbeat
|
|
119
|
+
curl -X PUT http://localhost:8080/__registry/heartbeat/my-service
|
|
273
120
|
|
|
274
|
-
#
|
|
275
|
-
curl -
|
|
121
|
+
# Deregister
|
|
122
|
+
curl -X DELETE http://localhost:8080/__registry/deregister/my-service
|
|
276
123
|
```
|
|
277
124
|
|
|
278
|
-
The proxy config is mounted as a Kubernetes ConfigMap — change it without rebuilding the image.
|
|
279
|
-
|
|
280
125
|
---
|
|
281
126
|
|
|
282
|
-
##
|
|
127
|
+
## Multi-Tenant Config (Nginx-style)
|
|
283
128
|
|
|
284
|
-
|
|
129
|
+
Drop extra config files into a `config.d/` folder — the proxy merges them automatically with zero downtime:
|
|
285
130
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
```yaml
|
|
289
|
-
autoScaling:
|
|
290
|
-
enabled: false
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
The proxy uses only the upstream servers listed in `config.yaml`. This is appropriate for production setups where you manage your own backend services.
|
|
294
|
-
|
|
295
|
-
### Dynamic mode
|
|
131
|
+
```bash
|
|
132
|
+
mkdir config.d
|
|
296
133
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
134
|
+
# Each tenant/app gets their own isolated file
|
|
135
|
+
echo "
|
|
136
|
+
server:
|
|
137
|
+
upstreams:
|
|
138
|
+
- id: tenant-a
|
|
139
|
+
url: http://localhost:4000
|
|
140
|
+
paths:
|
|
141
|
+
- path: /tenant-a
|
|
142
|
+
upstream: [tenant-a]
|
|
143
|
+
" > config.d/tenant-a.yaml
|
|
305
144
|
```
|
|
306
145
|
|
|
307
|
-
|
|
146
|
+
The proxy hot-reloads `config.d/` automatically whenever a file is added or changed.
|
|
308
147
|
|
|
309
148
|
---
|
|
310
149
|
|
|
311
150
|
## Admin API
|
|
312
151
|
|
|
313
|
-
All admin endpoints are available on the HTTPS port.
|
|
314
|
-
|
|
315
152
|
| Endpoint | Method | Description |
|
|
316
153
|
|---|---|---|
|
|
317
154
|
| `/__lb-stats` | GET | Load balancer stats + healthy upstreams |
|
|
318
155
|
| `/__cache-stats` | GET | Redis cache hit/miss stats |
|
|
319
156
|
| `/__registry` | GET | All registered services |
|
|
320
|
-
| `/__autoscaler-stats` | GET | Auto scaler status |
|
|
321
157
|
| `/__registry/register` | POST | Register a new upstream |
|
|
322
158
|
| `/__registry/deregister/:id` | DELETE | Deregister an upstream |
|
|
323
159
|
| `/__registry/heartbeat/:id` | PUT | Upstream heartbeat ping |
|
|
324
160
|
|
|
325
|
-
```bash
|
|
326
|
-
curl -k https://localhost:8443/__lb-stats
|
|
327
|
-
curl -k https://localhost:8443/__cache-stats
|
|
328
|
-
curl -k https://localhost:8443/__registry
|
|
329
|
-
curl -k https://localhost:8443/__autoscaler-stats
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
---
|
|
333
|
-
|
|
334
|
-
## Jenkins CI/CD Pipeline
|
|
335
|
-
|
|
336
|
-
A declarative `Jenkinsfile` is included in the project root.
|
|
337
|
-
|
|
338
|
-
**Pipeline stages:**
|
|
339
|
-
|
|
340
|
-
1. **Setup** — `npm ci` (deterministic install)
|
|
341
|
-
2. **Static Analysis** — Lint + `npm audit` (parallel)
|
|
342
|
-
3. **Unit Tests** — conditional on `RUN_TESTS` parameter
|
|
343
|
-
4. **Build Artifact** — `npm run build` (TypeScript → JavaScript)
|
|
344
|
-
5. **Deploy to Production** — branch `main` + `ENV_TYPE=prod` + manual approval gate
|
|
345
|
-
|
|
346
|
-
**Global options:** 1-hour timeout · last 10 builds retained · no concurrent builds · timestamps on every log line.
|
|
347
|
-
|
|
348
161
|
---
|
|
349
162
|
|
|
350
|
-
##
|
|
351
|
-
|
|
352
|
-
`sonar-project.properties` is included. To run a scan:
|
|
353
|
-
|
|
354
|
-
```bash
|
|
355
|
-
sonar-scanner \
|
|
356
|
-
-Dsonar.host.url=http://localhost:9000 \
|
|
357
|
-
-Dsonar.login=YOUR_SONAR_TOKEN
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
Scans the `src/` directory. Excludes `node_modules/`, `dist/`, certificates, and CI files.
|
|
361
|
-
|
|
362
|
-
---
|
|
363
|
-
|
|
364
|
-
## Security Scanning (Trivy)
|
|
365
|
-
|
|
366
|
-
```bash
|
|
367
|
-
# Scan dependencies
|
|
368
|
-
trivy fs .
|
|
369
|
-
|
|
370
|
-
# Scan the Docker image
|
|
371
|
-
docker build -t ninja-reverse-proxy:latest .
|
|
372
|
-
trivy image ninja-reverse-proxy:latest
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
---
|
|
376
|
-
|
|
377
|
-
## Project Structure
|
|
378
|
-
|
|
379
|
-
```
|
|
380
|
-
ninja-reverse-proxy/
|
|
381
|
-
├── src/ ← Proxy source (TypeScript)
|
|
382
|
-
│ ├── index.ts → CLI entry point
|
|
383
|
-
│ ├── server.ts → Master + Worker proxy engine
|
|
384
|
-
│ ├── loadBalancer.ts → Round-robin with circuit breaker
|
|
385
|
-
│ ├── auto-scaler.ts → Dynamic server scaling
|
|
386
|
-
│ ├── health.ts → Health checker (initial + continuous)
|
|
387
|
-
│ ├── Serviceregistry.ts → Service registry (register/heartbeat/deregister)
|
|
388
|
-
│ ├── cache.ts → Redis cache (get/set/invalidate/stats)
|
|
389
|
-
│ ├── rate-limiter.ts → Sliding window rate limiter
|
|
390
|
-
│ ├── config-schema.ts → Zod config validation schema
|
|
391
|
-
│ ├── config.ts → YAML parser
|
|
392
|
-
│ └── server-schema.ts → Worker IPC message schema
|
|
393
|
-
│
|
|
394
|
-
├── k8s/ ← Kubernetes manifests
|
|
395
|
-
│ ├── configmap.yaml
|
|
396
|
-
│ ├── tls-secret.yaml
|
|
397
|
-
│ ├── proxy-deployment.yaml
|
|
398
|
-
│ ├── proxy-service.yaml
|
|
399
|
-
│ └── README.md
|
|
400
|
-
│
|
|
401
|
-
├── examples/ ← Integration examples (NOT part of the proxy)
|
|
402
|
-
│ ├── docker-compose/ ← Full demo stack (backend-a + backend-b)
|
|
403
|
-
│ │ ├── server-template.js → Minimal demo backend
|
|
404
|
-
│ │ ├── Dockerfile.server → Demo backend image
|
|
405
|
-
│ │ ├── docker-compose.yml → Full demo stack
|
|
406
|
-
│ │ ├── config.yaml → Demo config
|
|
407
|
-
│ │ └── README.md
|
|
408
|
-
│ └── express/ ← Express.js integration example
|
|
409
|
-
│ ├── server.js
|
|
410
|
-
│ └── README.md
|
|
411
|
-
│
|
|
412
|
-
├── Dockerfile ← Proxy image (multi-stage build)
|
|
413
|
-
├── Jenkinsfile ← CI/CD declarative pipeline
|
|
414
|
-
├── sonar-project.properties ← SonarQube config
|
|
415
|
-
├── docker-compose.yml ← Proxy + Redis only
|
|
416
|
-
├── config.example.yaml ← Fully commented configuration template
|
|
417
|
-
├── .dockerignore
|
|
418
|
-
├── .gitignore
|
|
419
|
-
├── package.json
|
|
420
|
-
├── tsconfig.json
|
|
421
|
-
└── README.md
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
---
|
|
425
|
-
|
|
426
|
-
## Tech Stack
|
|
427
|
-
|
|
428
|
-
| Technology | Purpose |
|
|
429
|
-
|---|---|
|
|
430
|
-
| TypeScript | Full type safety |
|
|
431
|
-
| Node.js Cluster | Master/Worker multi-process architecture |
|
|
432
|
-
| Redis | Response caching |
|
|
433
|
-
| Zod | Schema validation for config and worker messages |
|
|
434
|
-
| YAML | Human-readable configuration |
|
|
435
|
-
| Commander | CLI entry point |
|
|
436
|
-
| Docker Compose | Orchestration |
|
|
437
|
-
| Kubernetes | Production cluster deployment |
|
|
438
|
-
| Jenkins | CI/CD pipeline |
|
|
439
|
-
| SonarQube | Static code analysis |
|
|
440
|
-
| Trivy | Container security scanning |
|
|
441
|
-
|
|
442
|
-
---
|
|
443
|
-
|
|
444
|
-
## Request Lifecycle
|
|
445
|
-
|
|
446
|
-
```
|
|
447
|
-
Client → :8080 HTTP → 301 redirect to HTTPS
|
|
448
|
-
Client → :8443 HTTPS
|
|
449
|
-
1. Rate limiter checks client IP — 429 if exceeded
|
|
450
|
-
2. GET requests → Redis cache checked — HIT returns instantly
|
|
451
|
-
3. Write requests (POST/PUT/PATCH/DELETE) → cache invalidated
|
|
452
|
-
4. Request body assembled from chunks
|
|
453
|
-
5. Load balancer picks a healthy upstream
|
|
454
|
-
6. Worker process forwards request over keepAlive TCP
|
|
455
|
-
7. Upstream responds → reply sent back via IPC
|
|
456
|
-
8. Master sends response to client + caches (GET)
|
|
457
|
-
9. On failure → circuit breaker records it, retry up to 2 times
|
|
458
|
-
```
|
|
459
|
-
|
|
460
|
-
---
|
|
461
|
-
|
|
462
|
-
## Performance Tips
|
|
163
|
+
## Configuration Reference
|
|
463
164
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
165
|
+
| Field | Default | Description |
|
|
166
|
+
|---|---|---|
|
|
167
|
+
| `server.listen` | `8080` | HTTP port — redirects all traffic to HTTPS |
|
|
168
|
+
| `server.httpsPort` | `8443` | HTTPS port — main entry point |
|
|
169
|
+
| `server.workers` | `2` | Set to your CPU core count |
|
|
170
|
+
| `loadBalancing.strategy` | `round-robin` | `round-robin` \| `least-connections` \| `ip-hash` \| `random` |
|
|
171
|
+
| `loadBalancing.failureThreshold` | `3` | Mark upstream DOWN after N consecutive failures |
|
|
172
|
+
| `loadBalancing.recoveryTimeMs` | `15000` | Retry a DOWN upstream after N ms |
|
|
173
|
+
| `cache.enabled` | `false` | Enable Redis GET response caching |
|
|
174
|
+
| `cache.ttlSeconds` | `60` | Cache TTL in seconds |
|
|
469
175
|
|
|
470
176
|
---
|
|
471
177
|
|
|
472
|
-
##
|
|
178
|
+
## Repository
|
|
473
179
|
|
|
474
|
-
|
|
180
|
+
[github.com/praveenkumar-co/reverse-proxy](https://github.com/praveenkumar-co/reverse-proxy)
|
|
475
181
|
|
|
476
182
|
---
|
|
477
183
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ninja-reverse-proxy",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "A production-grade reverse proxy with load balancing, circuit breaker, sticky sessions, and dynamic service registry.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -13,7 +13,16 @@
|
|
|
13
13
|
"dev": "tsc-watch --onSuccess \"node dist/index.js --config config.yaml\"",
|
|
14
14
|
"test": "tsc -p tsconfig.test.json && node --test dist-test/test"
|
|
15
15
|
},
|
|
16
|
-
"keywords": [
|
|
16
|
+
"keywords": [
|
|
17
|
+
"reverse-proxy",
|
|
18
|
+
"load-balancer",
|
|
19
|
+
"circuit-breaker",
|
|
20
|
+
"nginx",
|
|
21
|
+
"gateway",
|
|
22
|
+
"sticky-session",
|
|
23
|
+
"rate-limiter",
|
|
24
|
+
"proxy"
|
|
25
|
+
],
|
|
17
26
|
"author": "praveenkumar-co",
|
|
18
27
|
"license": "ISC",
|
|
19
28
|
"repository": {
|
|
@@ -29,10 +38,7 @@
|
|
|
29
38
|
},
|
|
30
39
|
"dependencies": {
|
|
31
40
|
"commander": "^14.0.3",
|
|
32
|
-
"express": "^5.2.1",
|
|
33
|
-
"node-utils-kit": "^1.2.4",
|
|
34
41
|
"redis": "^5.11.0",
|
|
35
|
-
"scalable-bloom-kit": "^1.0.6",
|
|
36
42
|
"yaml": "^2.8.2",
|
|
37
43
|
"zod": "^4.3.6"
|
|
38
44
|
}
|