@robiki/proxy 1.0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Robiki sp. z o.o
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.
package/README.md ADDED
@@ -0,0 +1,588 @@
1
+ # ๐Ÿš€ Robiki Proxy
2
+
3
+ > A high-performance, flexible HTTP/2 reverse proxy with WebSocket support, configurable routing, CORS, and request validation. Use it as an npm package in your Node.js application or as a standalone Docker container.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@robiki/proxy.svg)](https://www.npmjs.com/package/@robiki/proxy)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ ## โœจ Features
9
+
10
+ - **๐Ÿ”’ HTTP/2 & SSL/TLS Support**: Full HTTP/2 protocol support with automatic HTTP/1.1 fallback
11
+ - **๐Ÿ”Œ WebSocket Proxying**: Seamless WebSocket connection handling and proxying
12
+ - **๐ŸŒ Flexible Routing**: Configure routes by domain/host with wildcard support
13
+ - **๐Ÿ›ก๏ธ CORS Management**: Global and per-route CORS configuration
14
+ - **โœ… Request Validation**: Custom validation logic for authentication, rate limiting, etc.
15
+ - **๐Ÿ”„ URL Remapping**: Transform URLs before forwarding to target services
16
+ - **๐Ÿ“ฆ Dual Usage**: Use as npm package or Docker container
17
+ - **๐ŸŽฏ Multi-Port Support**: Listen on multiple ports simultaneously
18
+ - **โšก High Performance**: Built on Node.js native HTTP/2 implementation
19
+
20
+ ## ๐Ÿ“ฆ Installation
21
+
22
+ ### As an npm Package
23
+
24
+ ```bash
25
+ npm install @robiki/proxy
26
+ ```
27
+
28
+ ```bash
29
+ yarn add @robiki/proxy
30
+ ```
31
+
32
+ ### As a Docker Container
33
+
34
+ ```bash
35
+ docker pull robiki/proxy:latest
36
+ ```
37
+
38
+ Or build from source:
39
+
40
+ ```bash
41
+ docker build -t robiki/proxy .
42
+ ```
43
+
44
+ ## ๐Ÿš€ Quick Start
45
+
46
+ ### Using as npm Package
47
+
48
+ ```javascript
49
+ import { createProxy } from '@robiki/proxy';
50
+
51
+ const proxy = await createProxy({
52
+ ports: [443, 8080],
53
+ ssl: {
54
+ key: './certs/key.pem',
55
+ cert: './certs/cert.pem',
56
+ allowHTTP1: true,
57
+ },
58
+ routes: {
59
+ 'api.example.com': {
60
+ target: 'localhost:3000',
61
+ ssl: true,
62
+ },
63
+ 'example.com': {
64
+ target: 'localhost:8080',
65
+ ssl: false,
66
+ },
67
+ },
68
+ });
69
+
70
+ console.log('Proxy server is running!');
71
+ ```
72
+
73
+ ### Using with Docker
74
+
75
+ 1. Create a `proxy.config.json` file:
76
+
77
+ ```json
78
+ {
79
+ "ports": [443, 8080],
80
+ "ssl": {
81
+ "key": "/app/certs/key.pem",
82
+ "cert": "/app/certs/cert.pem",
83
+ "allowHTTP1": true
84
+ },
85
+ "routes": {
86
+ "api.example.com": {
87
+ "target": "backend-service:3000",
88
+ "ssl": true
89
+ },
90
+ "example.com": {
91
+ "target": "frontend-service:8080",
92
+ "ssl": false
93
+ }
94
+ }
95
+ }
96
+ ```
97
+
98
+ 2. Create a `docker-compose.yml`:
99
+
100
+ ```yaml
101
+ version: '3.8'
102
+
103
+ services:
104
+ proxy:
105
+ image: robiki/proxy:latest
106
+ ports:
107
+ - '443:443'
108
+ - '8080:8080'
109
+ volumes:
110
+ - ./proxy.config.json:/app/proxy.config.json:ro
111
+ - ./certs:/app/certs:ro
112
+ environment:
113
+ - PROXY_CONFIG=/app/proxy.config.json
114
+ networks:
115
+ - app-network
116
+
117
+ backend-service:
118
+ image: your-backend-image
119
+ networks:
120
+ - app-network
121
+
122
+ frontend-service:
123
+ image: your-frontend-image
124
+ networks:
125
+ - app-network
126
+
127
+ networks:
128
+ app-network:
129
+ driver: bridge
130
+ ```
131
+
132
+ 3. Start the services:
133
+
134
+ ```bash
135
+ docker-compose up -d
136
+ ```
137
+
138
+ ## ๐Ÿ“– Configuration
139
+
140
+ ### Configuration File
141
+
142
+ Create a `proxy.config.json` file with the following structure:
143
+
144
+ ```json
145
+ {
146
+ "ports": [443, 8080],
147
+ "ssl": {
148
+ "key": "./certs/key.pem",
149
+ "cert": "./certs/cert.pem",
150
+ "ca": "./certs/ca.pem",
151
+ "allowHTTP1": true
152
+ },
153
+ "cors": {
154
+ "origin": "*",
155
+ "methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
156
+ "allowedHeaders": ["Content-Type", "Authorization"],
157
+ "credentials": true,
158
+ "maxAge": 86400
159
+ },
160
+ "routes": {
161
+ "api.example.com": {
162
+ "target": "backend-service:3000",
163
+ "ssl": true,
164
+ "cors": {
165
+ "origin": ["https://example.com"],
166
+ "credentials": true
167
+ }
168
+ },
169
+ "*.example.com": {
170
+ "target": "wildcard-service:4000",
171
+ "ssl": true
172
+ }
173
+ }
174
+ }
175
+ ```
176
+
177
+ ### Environment Variables
178
+
179
+ You can also configure the proxy using environment variables:
180
+
181
+ ```bash
182
+ # SSL Configuration
183
+ SSL_KEY=/app/certs/key.pem
184
+ SSL_CERT=/app/certs/cert.pem
185
+ SSL_CA=/app/certs/ca.pem
186
+ SSL_ALLOW_HTTP1=true
187
+
188
+ # CORS Configuration
189
+ CORS_ORIGIN=*
190
+ CORS_METHODS=GET,POST,PUT,DELETE,OPTIONS
191
+ CORS_HEADERS=Content-Type,Authorization
192
+ CORS_CREDENTIALS=true
193
+ ```
194
+
195
+ ## ๐ŸŽฏ Advanced Usage
196
+
197
+ ### URL Remapping
198
+
199
+ Transform URLs before forwarding to target services:
200
+
201
+ ```javascript
202
+ const config = {
203
+ routes: {
204
+ 'api.example.com': {
205
+ target: 'backend:3000',
206
+ ssl: true,
207
+ remap: (url) => {
208
+ // Remove /api prefix
209
+ return url.replace(/^\/api/, '');
210
+ },
211
+ },
212
+ },
213
+ };
214
+ ```
215
+
216
+ ### Request Validation
217
+
218
+ Add custom validation logic for authentication, rate limiting, etc.:
219
+
220
+ ```javascript
221
+ const config = {
222
+ // Global validation
223
+ validate: async (info) => {
224
+ if (!info.headers.authorization) {
225
+ return {
226
+ status: false,
227
+ code: 401,
228
+ message: 'Unauthorized',
229
+ headers: { 'www-authenticate': 'Bearer' },
230
+ };
231
+ }
232
+ return { status: true };
233
+ },
234
+ routes: {
235
+ 'api.example.com': {
236
+ target: 'backend:3000',
237
+ ssl: true,
238
+ // Route-specific validation
239
+ validate: async (info) => {
240
+ const rateLimit = await checkRateLimit(info.remoteAddress);
241
+ if (!rateLimit.allowed) {
242
+ return {
243
+ status: false,
244
+ code: 429,
245
+ message: 'Too Many Requests',
246
+ };
247
+ }
248
+ return { status: true };
249
+ },
250
+ },
251
+ },
252
+ };
253
+ ```
254
+
255
+ ### Custom CORS Configuration
256
+
257
+ Configure CORS globally or per-route:
258
+
259
+ ```javascript
260
+ const config = {
261
+ // Global CORS
262
+ cors: {
263
+ origin: ['https://example.com', 'https://www.example.com'],
264
+ methods: ['GET', 'POST', 'PUT', 'DELETE'],
265
+ allowedHeaders: ['Content-Type', 'Authorization'],
266
+ credentials: true,
267
+ maxAge: 86400,
268
+ },
269
+ routes: {
270
+ 'api.example.com': {
271
+ target: 'backend:3000',
272
+ ssl: true,
273
+ // Route-specific CORS (overrides global)
274
+ cors: {
275
+ origin: '*',
276
+ credentials: false,
277
+ },
278
+ },
279
+ },
280
+ };
281
+ ```
282
+
283
+ ### Custom Handlers
284
+
285
+ Create custom request handlers for advanced use cases:
286
+
287
+ ```javascript
288
+ import { createCustomProxy } from '@robiki/proxy';
289
+
290
+ const customRestHandler = async (req, res) => {
291
+ if (req.url === '/health') {
292
+ res.writeHead(200, { 'content-type': 'application/json' });
293
+ return res.end(JSON.stringify({ status: 'ok' }));
294
+ }
295
+ // Fall back to default proxy behavior
296
+ const { restAPIProxyHandler } = await import('@robiki/proxy/connections');
297
+ return restAPIProxyHandler(req, res);
298
+ };
299
+
300
+ const proxy = await createCustomProxy(config, {
301
+ rest: customRestHandler,
302
+ websocket: customWebSocketHandler,
303
+ stream: customStreamHandler,
304
+ });
305
+ ```
306
+
307
+ ## ๐Ÿ”ง API Reference
308
+
309
+ ### `createProxy(config: ServerConfig): Promise<ProxyServer>`
310
+
311
+ Creates and starts a proxy server with the given configuration.
312
+
313
+ **Parameters:**
314
+
315
+ - `config`: Server configuration object
316
+
317
+ **Returns:** Promise that resolves to a `ProxyServer` instance
318
+
319
+ ### `ProxyServer`
320
+
321
+ **Methods:**
322
+
323
+ - `start()`: Start the proxy server
324
+ - `stop()`: Stop the proxy server
325
+ - `getConfig()`: Get the current configuration
326
+
327
+ ### Configuration Types
328
+
329
+ #### `ServerConfig`
330
+
331
+ ```typescript
332
+ interface ServerConfig {
333
+ ports?: number[];
334
+ ssl?: CertificateConfig;
335
+ routes: Record<string, RouteConfig>;
336
+ cors?: CorsConfig;
337
+ validate?: (info: ConnectionInfo) => Promise<ForwardValidationResult>;
338
+ }
339
+ ```
340
+
341
+ #### `RouteConfig`
342
+
343
+ ```typescript
344
+ interface RouteConfig {
345
+ target: string;
346
+ ssl?: boolean;
347
+ remap?: (url: string) => string;
348
+ cors?: CorsConfig;
349
+ validate?: (info: ConnectionInfo) => Promise<ForwardValidationResult>;
350
+ }
351
+ ```
352
+
353
+ #### `CorsConfig`
354
+
355
+ ```typescript
356
+ interface CorsConfig {
357
+ origin?: string | string[];
358
+ methods?: string[];
359
+ allowedHeaders?: string[];
360
+ exposedHeaders?: string[];
361
+ credentials?: boolean;
362
+ maxAge?: number;
363
+ }
364
+ ```
365
+
366
+ #### `ConnectionInfo`
367
+
368
+ ```typescript
369
+ interface ConnectionInfo {
370
+ id: number;
371
+ method: string;
372
+ path: string;
373
+ remoteAddress: string;
374
+ scheme: string;
375
+ authority: string;
376
+ origin: string;
377
+ headers: IncomingHttpHeaders;
378
+ query: URLSearchParams;
379
+ type: RequestType;
380
+ }
381
+ ```
382
+
383
+ ## ๐Ÿณ Docker Usage
384
+
385
+ ### Using in Another Project
386
+
387
+ 1. Add the proxy to your `docker-compose.yml`:
388
+
389
+ ```yaml
390
+ services:
391
+ proxy:
392
+ image: robiki/proxy:latest
393
+ ports:
394
+ - '443:443'
395
+ - '8080:8080'
396
+ volumes:
397
+ - ./proxy.config.json:/app/proxy.config.json:ro
398
+ - ./certs:/app/certs:ro
399
+ networks:
400
+ - your-network
401
+
402
+ your-service:
403
+ image: your-service-image
404
+ networks:
405
+ - your-network
406
+ ```
407
+
408
+ 2. Configure routes in `proxy.config.json` to point to your services
409
+
410
+ 3. Start your stack:
411
+
412
+ ```bash
413
+ docker-compose up -d
414
+ ```
415
+
416
+ ### Building Custom Image
417
+
418
+ Create a custom Dockerfile:
419
+
420
+ ```dockerfile
421
+ FROM robiki/proxy:latest
422
+
423
+ # Copy your configuration
424
+ COPY proxy.config.json /app/proxy.config.json
425
+ COPY certs /app/certs
426
+
427
+ # Set environment variables
428
+ ENV PROXY_CONFIG=/app/proxy.config.json
429
+ ```
430
+
431
+ ## ๐Ÿ“š Examples
432
+
433
+ Check the `examples/` directory for more usage examples:
434
+
435
+ - `basic-usage.js` - Simple proxy setup
436
+ - `advanced-usage.js` - Advanced features (validation, CORS, remapping)
437
+ - `custom-handlers.js` - Custom request handlers
438
+ - `docker-compose.example.yml` - Complete Docker setup
439
+
440
+ ## ๐Ÿ” SSL/TLS Certificates
441
+
442
+ ### Generating Self-Signed Certificates
443
+
444
+ For development:
445
+
446
+ ```bash
447
+ mkdir -p certs
448
+ openssl req -x509 -newkey rsa:4096 -keyout certs/key.pem -out certs/cert.pem -days 365 -nodes
449
+ ```
450
+
451
+ ### Using Let's Encrypt
452
+
453
+ For production, use Let's Encrypt certificates:
454
+
455
+ ```bash
456
+ certbot certonly --standalone -d example.com
457
+ ```
458
+
459
+ Then reference them in your config:
460
+
461
+ ```json
462
+ {
463
+ "ssl": {
464
+ "key": "/etc/letsencrypt/live/example.com/privkey.pem",
465
+ "cert": "/etc/letsencrypt/live/example.com/fullchain.pem"
466
+ }
467
+ }
468
+ ```
469
+
470
+ ## ๐Ÿค Contributing
471
+
472
+ Contributions are welcome! Please feel free to submit a Pull Request.
473
+
474
+ ## ๐Ÿ“„ License
475
+
476
+ MIT ยฉ Robiki sp. z o.o.
477
+
478
+ ## ๐Ÿ”— Links
479
+
480
+ - [GitHub Repository](https://github.com/robiki-ai/robiki-proxy)
481
+ - [npm Package](https://www.npmjs.com/package/@robiki/proxy)
482
+ - [Issue Tracker](https://github.com/robiki-ai/robiki-proxy/issues)
483
+
484
+ ## ๐Ÿ’ก Use Cases
485
+
486
+ - **Microservices Architecture**: Route requests to different services based on domain/path
487
+ - **Development Environment**: Local proxy for testing multiple services
488
+ - **API Gateway**: Centralized entry point with authentication and rate limiting
489
+ - **SSL Termination**: Handle SSL/TLS at the proxy level
490
+ - **CORS Management**: Centralized CORS configuration
491
+ - **Load Balancing**: Distribute traffic across multiple instances (with custom handlers)
492
+
493
+ ## ๐Ÿ› ๏ธ Troubleshooting
494
+
495
+ ### Port Already in Use
496
+
497
+ The proxy will automatically attempt to kill processes on the configured ports. If this fails, manually free the ports:
498
+
499
+ ```bash
500
+ lsof -ti:443 | xargs kill -9
501
+ lsof -ti:8080 | xargs kill -9
502
+ ```
503
+
504
+ ### SSL Certificate Errors
505
+
506
+ Ensure your certificate files are readable and in the correct format (PEM). For development, use self-signed certificates.
507
+
508
+ ### WebSocket Connection Issues
509
+
510
+ Make sure your WebSocket routes are configured with the correct protocol (ws/wss) and that the target service supports WebSocket connections.
511
+
512
+ ## ๐Ÿงช Testing
513
+
514
+ Robiki Proxy includes a comprehensive test suite covering unit tests, integration tests, and advanced scenarios.
515
+
516
+ ### Running Tests
517
+
518
+ ```bash
519
+ # Run all tests
520
+ yarn test
521
+
522
+ # Run tests in watch mode
523
+ yarn test:watch
524
+
525
+ # Run tests with coverage
526
+ yarn test:coverage
527
+
528
+ # Run tests with UI
529
+ yarn test:ui
530
+ ```
531
+
532
+ ### Test Coverage
533
+
534
+ The test suite includes:
535
+
536
+ - **Unit Tests**: Configuration, utilities, header conversion, CORS handling
537
+ - **Integration Tests**: HTTP proxying, route resolution, validation, config loading
538
+ - **Advanced Tests**: WebSocket proxying, HTTP/2 streams, concurrent connections
539
+ - **Docker Tests**: Container builds, config loading, runtime behavior
540
+
541
+ ### Docker Tests
542
+
543
+ Run Docker integration tests:
544
+
545
+ ```bash
546
+ # Full Docker integration test
547
+ yarn test:docker
548
+
549
+ # Test config loading specifically
550
+ yarn test:docker:config
551
+
552
+ # Run all tests (unit + integration + Docker)
553
+ yarn test:all
554
+ ```
555
+
556
+ Or using Make:
557
+
558
+ ```bash
559
+ # Quick Docker build test
560
+ make test-docker
561
+
562
+ # Full integration test suite
563
+ make test-docker-full
564
+
565
+ # Config loading test
566
+ make test-docker-config
567
+
568
+ # Docker Compose test
569
+ make test-docker-compose
570
+ ```
571
+
572
+ See the [Docker Tests README](tests/docker/README.md) for more details.
573
+
574
+ ## ๐Ÿ“Š Performance
575
+
576
+ The proxy is built on Node.js native HTTP/2 implementation and is designed for high performance:
577
+
578
+ - Efficient stream handling
579
+ - Minimal overhead
580
+ - Connection pooling
581
+ - Automatic HTTP/1.1 fallback
582
+
583
+ For production deployments, consider:
584
+
585
+ - Using a process manager (PM2, systemd)
586
+ - Enabling clustering for multi-core systems
587
+ - Monitoring with health checks
588
+ - Setting up proper logging