@infodb/revx 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.
- package/LICENSE +21 -0
- package/README.md +376 -0
- package/bin/cli.js +2 -0
- package/dist/commands/init.d.ts +6 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +139 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/start.d.ts +4 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +160 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/validate.d.ts +4 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +50 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/config.d.ts +107 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +102 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/logger.d.ts +14 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +58 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/proxy.d.ts +24 -0
- package/dist/utils/proxy.d.ts.map +1 -0
- package/dist/utils/proxy.js +134 -0
- package/dist/utils/proxy.js.map +1 -0
- package/package.json +60 -0
- package/sample/revx.simple.yaml +15 -0
- package/sample/revx.yaml +95 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { createProxyMiddleware } from 'http-proxy-middleware';
|
|
2
|
+
export class LoadBalancer {
|
|
3
|
+
constructor(targets, strategy = 'round-robin', logger) {
|
|
4
|
+
this.targets = targets;
|
|
5
|
+
this.strategy = strategy;
|
|
6
|
+
this.logger = logger;
|
|
7
|
+
this.currentIndex = 0;
|
|
8
|
+
this.targetHealth = new Map();
|
|
9
|
+
targets.forEach(target => this.targetHealth.set(target, true));
|
|
10
|
+
}
|
|
11
|
+
getTarget(req) {
|
|
12
|
+
const healthyTargets = this.targets.filter(t => this.targetHealth.get(t));
|
|
13
|
+
if (healthyTargets.length === 0) {
|
|
14
|
+
this.logger.warning('All targets are unhealthy, using first target');
|
|
15
|
+
return this.targets[0];
|
|
16
|
+
}
|
|
17
|
+
switch (this.strategy) {
|
|
18
|
+
case 'random':
|
|
19
|
+
return healthyTargets[Math.floor(Math.random() * healthyTargets.length)];
|
|
20
|
+
case 'ip-hash':
|
|
21
|
+
if (req) {
|
|
22
|
+
const ip = req.ip || req.socket.remoteAddress || '';
|
|
23
|
+
const hash = this.hashCode(ip);
|
|
24
|
+
return healthyTargets[Math.abs(hash) % healthyTargets.length];
|
|
25
|
+
}
|
|
26
|
+
return healthyTargets[0];
|
|
27
|
+
case 'round-robin':
|
|
28
|
+
default:
|
|
29
|
+
const target = healthyTargets[this.currentIndex % healthyTargets.length];
|
|
30
|
+
this.currentIndex = (this.currentIndex + 1) % healthyTargets.length;
|
|
31
|
+
return target;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
markUnhealthy(target) {
|
|
35
|
+
this.targetHealth.set(target, false);
|
|
36
|
+
this.logger.warning(`Target marked as unhealthy: ${target}`);
|
|
37
|
+
}
|
|
38
|
+
markHealthy(target) {
|
|
39
|
+
this.targetHealth.set(target, true);
|
|
40
|
+
this.logger.verbose(`Target marked as healthy: ${target}`);
|
|
41
|
+
}
|
|
42
|
+
hashCode(str) {
|
|
43
|
+
let hash = 0;
|
|
44
|
+
for (let i = 0; i < str.length; i++) {
|
|
45
|
+
const char = str.charCodeAt(i);
|
|
46
|
+
hash = ((hash << 5) - hash) + char;
|
|
47
|
+
hash = hash & hash;
|
|
48
|
+
}
|
|
49
|
+
return hash;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export class ProxyManager {
|
|
53
|
+
constructor(logger) {
|
|
54
|
+
this.logger = logger;
|
|
55
|
+
this.loadBalancers = new Map();
|
|
56
|
+
}
|
|
57
|
+
createProxyMiddleware(route) {
|
|
58
|
+
const options = {
|
|
59
|
+
changeOrigin: route.changeOrigin ?? true,
|
|
60
|
+
ws: route.ws ?? false,
|
|
61
|
+
pathRewrite: route.pathRewrite,
|
|
62
|
+
timeout: route.options?.timeout,
|
|
63
|
+
followRedirects: route.options?.followRedirects,
|
|
64
|
+
on: {
|
|
65
|
+
proxyReq: (proxyReq, req) => {
|
|
66
|
+
if (route.options?.headers) {
|
|
67
|
+
Object.entries(route.options.headers).forEach(([key, value]) => {
|
|
68
|
+
proxyReq.setHeader(key, value);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (route.transform?.request?.headers?.add) {
|
|
72
|
+
Object.entries(route.transform.request.headers.add).forEach(([key, value]) => {
|
|
73
|
+
proxyReq.setHeader(key, value);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
if (route.transform?.request?.headers?.remove) {
|
|
77
|
+
route.transform.request.headers.remove.forEach(header => {
|
|
78
|
+
proxyReq.removeHeader(header);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
this.logger.verbose('Proxy request', {
|
|
82
|
+
method: req.method,
|
|
83
|
+
path: req.url,
|
|
84
|
+
target: proxyReq.getHeader('host')
|
|
85
|
+
});
|
|
86
|
+
},
|
|
87
|
+
proxyRes: (proxyRes, req, res) => {
|
|
88
|
+
if (route.transform?.response?.headers?.add) {
|
|
89
|
+
Object.entries(route.transform.response.headers.add).forEach(([key, value]) => {
|
|
90
|
+
proxyRes.headers[key.toLowerCase()] = value;
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
if (route.transform?.response?.headers?.remove) {
|
|
94
|
+
route.transform.response.headers.remove.forEach(header => {
|
|
95
|
+
delete proxyRes.headers[header.toLowerCase()];
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
this.logger.verbose('Proxy response', {
|
|
99
|
+
statusCode: proxyRes.statusCode,
|
|
100
|
+
path: req.url
|
|
101
|
+
});
|
|
102
|
+
},
|
|
103
|
+
error: (err, req, res) => {
|
|
104
|
+
this.logger.error(`Proxy error: ${err.message}`);
|
|
105
|
+
const serverRes = res;
|
|
106
|
+
if (!serverRes.headersSent) {
|
|
107
|
+
serverRes.writeHead(502, { 'Content-Type': 'application/json' });
|
|
108
|
+
}
|
|
109
|
+
serverRes.end(JSON.stringify({
|
|
110
|
+
error: 'Bad Gateway',
|
|
111
|
+
message: 'Failed to proxy request'
|
|
112
|
+
}));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
if (route.targets && route.targets.length > 0) {
|
|
117
|
+
const balancer = new LoadBalancer(route.targets, route.strategy || 'round-robin', this.logger);
|
|
118
|
+
this.loadBalancers.set(route.path, balancer);
|
|
119
|
+
options.router = (req) => {
|
|
120
|
+
return balancer.getTarget(req);
|
|
121
|
+
};
|
|
122
|
+
this.logger.info(`Load balancer configured for ${route.path} with ${route.targets.length} targets (${route.strategy || 'round-robin'})`);
|
|
123
|
+
}
|
|
124
|
+
else if (route.target) {
|
|
125
|
+
options.target = route.target;
|
|
126
|
+
this.logger.info(`Proxy configured: ${route.path} -> ${route.target}`);
|
|
127
|
+
}
|
|
128
|
+
return createProxyMiddleware(options);
|
|
129
|
+
}
|
|
130
|
+
getLoadBalancer(path) {
|
|
131
|
+
return this.loadBalancers.get(path);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=proxy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/utils/proxy.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@infodb/revx",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Reverse proxy CLI tool with YAML configuration",
|
|
5
|
+
"homepage": "https://github.com/tamuto/infodb-cli/",
|
|
6
|
+
"bugs": "https://github.com/tamuto/infodb-cli/issues",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/tamuto/infodb-cli",
|
|
10
|
+
"directory": "revx"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"reverse-proxy",
|
|
14
|
+
"proxy",
|
|
15
|
+
"cli",
|
|
16
|
+
"express",
|
|
17
|
+
"yaml",
|
|
18
|
+
"http-proxy"
|
|
19
|
+
],
|
|
20
|
+
"author": "tamuto <tamuto@infodb.jp>",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"main": "dist/index.js",
|
|
23
|
+
"type": "module",
|
|
24
|
+
"bin": {
|
|
25
|
+
"revx": "./bin/cli.js"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"bin",
|
|
29
|
+
"dist",
|
|
30
|
+
"sample"
|
|
31
|
+
],
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=18.0.0"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"chalk": "^5.6.2",
|
|
37
|
+
"commander": "^14.0.2",
|
|
38
|
+
"cors": "^2.8.5",
|
|
39
|
+
"express": "^5.1.0",
|
|
40
|
+
"http-proxy-middleware": "^3.0.3",
|
|
41
|
+
"morgan": "^1.10.0",
|
|
42
|
+
"yaml": "^2.8.1"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/cors": "^2.8.17",
|
|
46
|
+
"@types/express": "^5.0.5",
|
|
47
|
+
"@types/morgan": "^1.9.9",
|
|
48
|
+
"@types/node": "^24.10.1",
|
|
49
|
+
"tsx": "^4.20.6",
|
|
50
|
+
"typescript": "^5.9.3"
|
|
51
|
+
},
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"access": "public"
|
|
54
|
+
},
|
|
55
|
+
"scripts": {
|
|
56
|
+
"dev": "tsx src/index.ts",
|
|
57
|
+
"build": "tsc",
|
|
58
|
+
"start": "node dist/index.js"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# revx.simple.yaml - Simple Reverse Proxy Configuration
|
|
2
|
+
|
|
3
|
+
server:
|
|
4
|
+
port: 3000
|
|
5
|
+
|
|
6
|
+
routes:
|
|
7
|
+
- path: "/api/*"
|
|
8
|
+
target: "http://localhost:4000"
|
|
9
|
+
pathRewrite:
|
|
10
|
+
"^/api": ""
|
|
11
|
+
|
|
12
|
+
- path: "/auth/*"
|
|
13
|
+
target: "http://localhost:5000"
|
|
14
|
+
pathRewrite:
|
|
15
|
+
"^/auth": ""
|
package/sample/revx.yaml
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# revx.yaml - Reverse Proxy Configuration Example
|
|
2
|
+
|
|
3
|
+
# Server settings
|
|
4
|
+
server:
|
|
5
|
+
port: 3000
|
|
6
|
+
host: 0.0.0.0
|
|
7
|
+
name: "My Reverse Proxy"
|
|
8
|
+
|
|
9
|
+
# Global configuration
|
|
10
|
+
global:
|
|
11
|
+
# Request timeout in milliseconds
|
|
12
|
+
timeout: 30000
|
|
13
|
+
|
|
14
|
+
# CORS settings
|
|
15
|
+
cors:
|
|
16
|
+
enabled: true
|
|
17
|
+
origin: "*"
|
|
18
|
+
methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"]
|
|
19
|
+
credentials: true
|
|
20
|
+
|
|
21
|
+
# Logging settings
|
|
22
|
+
logging:
|
|
23
|
+
enabled: true
|
|
24
|
+
format: "combined" # combined | dev | common | short | tiny
|
|
25
|
+
level: "info" # error | warn | info | debug
|
|
26
|
+
|
|
27
|
+
# Route definitions
|
|
28
|
+
routes:
|
|
29
|
+
# Example 1: Simple proxy to API server
|
|
30
|
+
- path: "/api/*"
|
|
31
|
+
target: "http://localhost:4000"
|
|
32
|
+
changeOrigin: true
|
|
33
|
+
pathRewrite:
|
|
34
|
+
"^/api": ""
|
|
35
|
+
options:
|
|
36
|
+
timeout: 5000
|
|
37
|
+
headers:
|
|
38
|
+
X-Forwarded-Host: "${HOST}"
|
|
39
|
+
|
|
40
|
+
# Example 2: WebSocket proxy
|
|
41
|
+
- path: "/ws"
|
|
42
|
+
target: "ws://localhost:5000"
|
|
43
|
+
ws: true
|
|
44
|
+
changeOrigin: true
|
|
45
|
+
|
|
46
|
+
# Example 3: Load balancing with multiple targets
|
|
47
|
+
- path: "/balanced/*"
|
|
48
|
+
targets:
|
|
49
|
+
- "http://localhost:8001"
|
|
50
|
+
- "http://localhost:8002"
|
|
51
|
+
- "http://localhost:8003"
|
|
52
|
+
strategy: "round-robin" # round-robin | random | ip-hash
|
|
53
|
+
pathRewrite:
|
|
54
|
+
"^/balanced": ""
|
|
55
|
+
healthCheck:
|
|
56
|
+
enabled: true
|
|
57
|
+
interval: 30000
|
|
58
|
+
path: "/health"
|
|
59
|
+
timeout: 3000
|
|
60
|
+
|
|
61
|
+
# Example 4: Request/Response transformation
|
|
62
|
+
- path: "/transform/*"
|
|
63
|
+
target: "http://localhost:6000"
|
|
64
|
+
changeOrigin: true
|
|
65
|
+
transform:
|
|
66
|
+
request:
|
|
67
|
+
headers:
|
|
68
|
+
add:
|
|
69
|
+
X-API-Version: "v2"
|
|
70
|
+
remove:
|
|
71
|
+
- "Cookie"
|
|
72
|
+
response:
|
|
73
|
+
headers:
|
|
74
|
+
add:
|
|
75
|
+
X-Proxy-Server: "revx"
|
|
76
|
+
remove:
|
|
77
|
+
- "Server"
|
|
78
|
+
|
|
79
|
+
# Middleware configuration
|
|
80
|
+
middleware:
|
|
81
|
+
# Request ID middleware
|
|
82
|
+
- type: "requestId"
|
|
83
|
+
enabled: true
|
|
84
|
+
headerName: "X-Request-ID"
|
|
85
|
+
|
|
86
|
+
# Compression middleware
|
|
87
|
+
- type: "compression"
|
|
88
|
+
enabled: true
|
|
89
|
+
threshold: 1024
|
|
90
|
+
|
|
91
|
+
# SSL/TLS settings (optional)
|
|
92
|
+
# ssl:
|
|
93
|
+
# enabled: false
|
|
94
|
+
# key: "/path/to/private.key"
|
|
95
|
+
# cert: "/path/to/certificate.crt"
|