@responsedotok/shufffle 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.md +9 -0
- package/README.md +91 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/src/cli/help.d.ts +1 -0
- package/dist/cjs/src/cli/help.js +54 -0
- package/dist/cjs/src/cli/index.d.ts +1 -0
- package/dist/cjs/src/cli/index.js +96 -0
- package/dist/cjs/src/cli/parse-args.d.ts +9 -0
- package/dist/cjs/src/cli/parse-args.js +68 -0
- package/dist/cjs/src/config/config.d.ts +16 -0
- package/dist/cjs/src/config/config.js +184 -0
- package/dist/cjs/src/env-overrides.d.ts +7 -0
- package/dist/cjs/src/env-overrides.js +37 -0
- package/dist/cjs/src/index.d.ts +10 -0
- package/dist/cjs/src/index.js +10 -0
- package/dist/cjs/src/lib/constants/hop-by-hop-headers.d.ts +1 -0
- package/dist/cjs/src/lib/constants/hop-by-hop-headers.js +13 -0
- package/dist/cjs/src/lib/services/handlers/http-handler.d.ts +32 -0
- package/dist/cjs/src/lib/services/handlers/http-handler.js +226 -0
- package/dist/cjs/src/lib/services/handlers/websocket-handler.d.ts +11 -0
- package/dist/cjs/src/lib/services/handlers/websocket-handler.js +100 -0
- package/dist/cjs/src/lib/services/headers/headers-service.d.ts +18 -0
- package/dist/cjs/src/lib/services/headers/headers-service.js +94 -0
- package/dist/cjs/src/lib/services/health/health-service.d.ts +15 -0
- package/dist/cjs/src/lib/services/health/health-service.js +65 -0
- package/dist/cjs/src/lib/services/load-balancers/create-balancer.d.ts +3 -0
- package/dist/cjs/src/lib/services/load-balancers/create-balancer.js +21 -0
- package/dist/cjs/src/lib/services/load-balancers/load-balancer.d.ts +4 -0
- package/dist/cjs/src/lib/services/load-balancers/load-balancer.js +6 -0
- package/dist/cjs/src/lib/services/load-balancers/random-balancer.d.ts +5 -0
- package/dist/cjs/src/lib/services/load-balancers/random-balancer.js +14 -0
- package/dist/cjs/src/lib/services/load-balancers/round-robin-balancer.d.ts +6 -0
- package/dist/cjs/src/lib/services/load-balancers/round-robin-balancer.js +16 -0
- package/dist/cjs/src/lib/services/load-balancers/weighted-balancer.d.ts +5 -0
- package/dist/cjs/src/lib/services/load-balancers/weighted-balancer.js +27 -0
- package/dist/cjs/src/lib/services/proxy/proxy-server.d.ts +16 -0
- package/dist/cjs/src/lib/services/proxy/proxy-server.js +118 -0
- package/dist/cjs/src/lib/types/config.d.ts +17 -0
- package/dist/cjs/src/lib/types/config.js +2 -0
- package/dist/cjs/src/lib/types/context.d.ts +10 -0
- package/dist/cjs/src/lib/types/context.js +2 -0
- package/dist/cjs/src/lib/types/header-rules.d.ts +6 -0
- package/dist/cjs/src/lib/types/header-rules.js +2 -0
- package/dist/cjs/src/lib/types/hooks.d.ts +6 -0
- package/dist/cjs/src/lib/types/hooks.js +2 -0
- package/dist/cjs/src/lib/types/load-balancer-strategy.d.ts +5 -0
- package/dist/cjs/src/lib/types/load-balancer-strategy.js +9 -0
- package/dist/cjs/src/lib/types/log.d.ts +8 -0
- package/dist/cjs/src/lib/types/log.js +10 -0
- package/dist/cjs/src/lib/types/route-match.d.ts +1 -0
- package/dist/cjs/src/lib/types/route-match.js +2 -0
- package/dist/cjs/src/lib/types/route-rewrite.d.ts +5 -0
- package/dist/cjs/src/lib/types/route-rewrite.js +2 -0
- package/dist/cjs/src/lib/types/route.d.ts +14 -0
- package/dist/cjs/src/lib/types/route.js +2 -0
- package/dist/cjs/src/lib/types/upstream.d.ts +6 -0
- package/dist/cjs/src/lib/types/upstream.js +2 -0
- package/dist/cjs/src/logger/logger.d.ts +10 -0
- package/dist/cjs/src/logger/logger.js +39 -0
- package/dist/cjs/src/utils/is-match.d.ts +2 -0
- package/dist/cjs/src/utils/is-match.js +14 -0
- package/dist/cjs/src/utils/match-route.d.ts +2 -0
- package/dist/cjs/src/utils/match-route.js +11 -0
- package/dist/cjs/src/utils/rewrite-path.d.ts +2 -0
- package/dist/cjs/src/utils/rewrite-path.js +23 -0
- package/dist/src/cli/help.d.ts +2 -0
- package/dist/src/cli/help.d.ts.map +1 -0
- package/dist/src/cli/help.js.map +1 -0
- package/dist/src/cli/help.mjs +52 -0
- package/dist/src/cli/index.d.ts +2 -0
- package/dist/src/cli/index.d.ts.map +1 -0
- package/dist/src/cli/index.js.map +1 -0
- package/dist/src/cli/index.mjs +91 -0
- package/dist/src/cli/parse-args.d.ts +10 -0
- package/dist/src/cli/parse-args.d.ts.map +1 -0
- package/dist/src/cli/parse-args.js.map +1 -0
- package/dist/src/cli/parse-args.mjs +66 -0
- package/dist/src/config/config.d.ts +17 -0
- package/dist/src/config/config.d.ts.map +1 -0
- package/dist/src/config/config.js.map +1 -0
- package/dist/src/config/config.mjs +145 -0
- package/dist/src/env-overrides.d.ts +8 -0
- package/dist/src/env-overrides.d.ts.map +1 -0
- package/dist/src/env-overrides.js.map +1 -0
- package/dist/src/env-overrides.mjs +34 -0
- package/dist/src/index.d.ts +11 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/index.mjs +4 -0
- package/dist/src/lib/constants/hop-by-hop-headers.d.ts +2 -0
- package/dist/src/lib/constants/hop-by-hop-headers.d.ts.map +1 -0
- package/dist/src/lib/constants/hop-by-hop-headers.js.map +1 -0
- package/dist/src/lib/constants/hop-by-hop-headers.mjs +11 -0
- package/dist/src/lib/services/handlers/http-handler.d.ts +33 -0
- package/dist/src/lib/services/handlers/http-handler.d.ts.map +1 -0
- package/dist/src/lib/services/handlers/http-handler.js.map +1 -0
- package/dist/src/lib/services/handlers/http-handler.mjs +220 -0
- package/dist/src/lib/services/handlers/websocket-handler.d.ts +12 -0
- package/dist/src/lib/services/handlers/websocket-handler.d.ts.map +1 -0
- package/dist/src/lib/services/handlers/websocket-handler.js.map +1 -0
- package/dist/src/lib/services/handlers/websocket-handler.mjs +94 -0
- package/dist/src/lib/services/headers/headers-service.d.ts +19 -0
- package/dist/src/lib/services/headers/headers-service.d.ts.map +1 -0
- package/dist/src/lib/services/headers/headers-service.js.map +1 -0
- package/dist/src/lib/services/headers/headers-service.mjs +91 -0
- package/dist/src/lib/services/health/health-service.d.ts +16 -0
- package/dist/src/lib/services/health/health-service.d.ts.map +1 -0
- package/dist/src/lib/services/health/health-service.js.map +1 -0
- package/dist/src/lib/services/health/health-service.mjs +59 -0
- package/dist/src/lib/services/load-balancers/create-balancer.d.ts +4 -0
- package/dist/src/lib/services/load-balancers/create-balancer.d.ts.map +1 -0
- package/dist/src/lib/services/load-balancers/create-balancer.js.map +1 -0
- package/dist/src/lib/services/load-balancers/create-balancer.mjs +19 -0
- package/dist/src/lib/services/load-balancers/load-balancer.d.ts +5 -0
- package/dist/src/lib/services/load-balancers/load-balancer.d.ts.map +1 -0
- package/dist/src/lib/services/load-balancers/load-balancer.js.map +1 -0
- package/dist/src/lib/services/load-balancers/load-balancer.mjs +3 -0
- package/dist/src/lib/services/load-balancers/random-balancer.d.ts +6 -0
- package/dist/src/lib/services/load-balancers/random-balancer.d.ts.map +1 -0
- package/dist/src/lib/services/load-balancers/random-balancer.js.map +1 -0
- package/dist/src/lib/services/load-balancers/random-balancer.mjs +11 -0
- package/dist/src/lib/services/load-balancers/round-robin-balancer.d.ts +7 -0
- package/dist/src/lib/services/load-balancers/round-robin-balancer.d.ts.map +1 -0
- package/dist/src/lib/services/load-balancers/round-robin-balancer.js.map +1 -0
- package/dist/src/lib/services/load-balancers/round-robin-balancer.mjs +13 -0
- package/dist/src/lib/services/load-balancers/weighted-balancer.d.ts +6 -0
- package/dist/src/lib/services/load-balancers/weighted-balancer.d.ts.map +1 -0
- package/dist/src/lib/services/load-balancers/weighted-balancer.js.map +1 -0
- package/dist/src/lib/services/load-balancers/weighted-balancer.mjs +24 -0
- package/dist/src/lib/services/proxy/proxy-server.d.ts +17 -0
- package/dist/src/lib/services/proxy/proxy-server.d.ts.map +1 -0
- package/dist/src/lib/services/proxy/proxy-server.js.map +1 -0
- package/dist/src/lib/services/proxy/proxy-server.mjs +111 -0
- package/dist/src/lib/types/config.d.ts +18 -0
- package/dist/src/lib/types/config.d.ts.map +1 -0
- package/dist/src/lib/types/config.js.map +1 -0
- package/dist/src/lib/types/config.mjs +2 -0
- package/dist/src/lib/types/context.d.ts +11 -0
- package/dist/src/lib/types/context.d.ts.map +1 -0
- package/dist/src/lib/types/context.js.map +1 -0
- package/dist/src/lib/types/context.mjs +2 -0
- package/dist/src/lib/types/header-rules.d.ts +7 -0
- package/dist/src/lib/types/header-rules.d.ts.map +1 -0
- package/dist/src/lib/types/header-rules.js.map +1 -0
- package/dist/src/lib/types/header-rules.mjs +2 -0
- package/dist/src/lib/types/hooks.d.ts +7 -0
- package/dist/src/lib/types/hooks.d.ts.map +1 -0
- package/dist/src/lib/types/hooks.js.map +1 -0
- package/dist/src/lib/types/hooks.mjs +2 -0
- package/dist/src/lib/types/load-balancer-strategy.d.ts +6 -0
- package/dist/src/lib/types/load-balancer-strategy.d.ts.map +1 -0
- package/dist/src/lib/types/load-balancer-strategy.js.map +1 -0
- package/dist/src/lib/types/load-balancer-strategy.mjs +7 -0
- package/dist/src/lib/types/log.d.ts +9 -0
- package/dist/src/lib/types/log.d.ts.map +1 -0
- package/dist/src/lib/types/log.js.map +1 -0
- package/dist/src/lib/types/log.mjs +8 -0
- package/dist/src/lib/types/route-match.d.ts +2 -0
- package/dist/src/lib/types/route-match.d.ts.map +1 -0
- package/dist/src/lib/types/route-match.js.map +1 -0
- package/dist/src/lib/types/route-match.mjs +2 -0
- package/dist/src/lib/types/route-rewrite.d.ts +6 -0
- package/dist/src/lib/types/route-rewrite.d.ts.map +1 -0
- package/dist/src/lib/types/route-rewrite.js.map +1 -0
- package/dist/src/lib/types/route-rewrite.mjs +2 -0
- package/dist/src/lib/types/route.d.ts +15 -0
- package/dist/src/lib/types/route.d.ts.map +1 -0
- package/dist/src/lib/types/route.js.map +1 -0
- package/dist/src/lib/types/route.mjs +2 -0
- package/dist/src/lib/types/upstream.d.ts +7 -0
- package/dist/src/lib/types/upstream.d.ts.map +1 -0
- package/dist/src/lib/types/upstream.js.map +1 -0
- package/dist/src/lib/types/upstream.mjs +2 -0
- package/dist/src/logger/logger.d.ts +11 -0
- package/dist/src/logger/logger.d.ts.map +1 -0
- package/dist/src/logger/logger.js.map +1 -0
- package/dist/src/logger/logger.mjs +36 -0
- package/dist/src/utils/is-match.d.ts +3 -0
- package/dist/src/utils/is-match.d.ts.map +1 -0
- package/dist/src/utils/is-match.js.map +1 -0
- package/dist/src/utils/is-match.mjs +12 -0
- package/dist/src/utils/match-route.d.ts +3 -0
- package/dist/src/utils/match-route.d.ts.map +1 -0
- package/dist/src/utils/match-route.js.map +1 -0
- package/dist/src/utils/match-route.mjs +9 -0
- package/dist/src/utils/rewrite-path.d.ts +3 -0
- package/dist/src/utils/rewrite-path.d.ts.map +1 -0
- package/dist/src/utils/rewrite-path.js.map +1 -0
- package/dist/src/utils/rewrite-path.mjs +21 -0
- package/package.json +63 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright 2026 Adam Robson
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# shufffle
|
|
2
|
+
|
|
3
|
+
A zero-dependency, config-driven reverse proxy for Node.js. Define routes and upstreams in JSON, run it from the CLI, or embed it in your own server.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @responsedotok/shufffle
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Requires Node.js >= 22.
|
|
12
|
+
|
|
13
|
+
## CLI Usage
|
|
14
|
+
|
|
15
|
+
Create `proxy.config.json`:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"port": 8080,
|
|
20
|
+
"balancer": "round-robin",
|
|
21
|
+
"routes": [
|
|
22
|
+
{
|
|
23
|
+
"match": "/api",
|
|
24
|
+
"rewrite": { "stripPrefix": "/api" },
|
|
25
|
+
"upstreams": [
|
|
26
|
+
{ "host": "localhost", "port": 3001 },
|
|
27
|
+
{ "host": "localhost", "port": 3002 }
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"match": "/",
|
|
32
|
+
"upstreams": [{ "host": "localhost", "port": 3000 }]
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Run it:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npx shufffle --config ./proxy.config.json
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
CLI flags: `-c/--config`, `-l/--log-level`, `-e/--env key=value`, `-b/--balancer`, `-h/--help`.
|
|
45
|
+
|
|
46
|
+
## Programmatic Usage
|
|
47
|
+
|
|
48
|
+
Create an async function, import `createProxy()`, and call it with await. pass an object
|
|
49
|
+
with the following shapes `{ port: number, routes: Route* }`. instead of calling `listen()` is async and starts the server for you — `await` it; don't call `listen()` yourself.
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import { createProxy } from "@responsedotok/shufffle";
|
|
53
|
+
|
|
54
|
+
async function main() {
|
|
55
|
+
const proxy = await createProxy({
|
|
56
|
+
port: 8080,
|
|
57
|
+
routes: [
|
|
58
|
+
{ match: "/", upstreams: [{ host: "localhost", port: 3000 }] },
|
|
59
|
+
],
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
process.on("SIGTERM", () => proxy.close());
|
|
63
|
+
process.on("SIGINT", () => proxy.close());
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
main().catch((err) => {
|
|
67
|
+
console.error(err);
|
|
68
|
+
process.exit(1);
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
If you'd rather control the lifecycle yourself, construct the server directly:
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import { ProxyServer } from "@responsedotok/shufffle";
|
|
76
|
+
|
|
77
|
+
const proxy = new ProxyServer({ port: 8080, routes: [/* … */] });
|
|
78
|
+
await proxy.listen();
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Features
|
|
82
|
+
|
|
83
|
+
- Path-prefix or function-based route matching
|
|
84
|
+
- Multiple upstreams per route with `round-robin`, `random`, or `weighted` load balancing
|
|
85
|
+
- Path rewrites (e.g. `stripPrefix`)
|
|
86
|
+
- Per-route and global header rules
|
|
87
|
+
- Configurable timeouts, max body size, and `X-Forwarded-For` forwarding
|
|
88
|
+
|
|
89
|
+
## License
|
|
90
|
+
|
|
91
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function printHelp(): void;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.printHelp = printHelp;
|
|
4
|
+
function printHelp() {
|
|
5
|
+
console.info(`
|
|
6
|
+
shufffle — Node Reverse Proxy
|
|
7
|
+
|
|
8
|
+
**USAGE**
|
|
9
|
+
|
|
10
|
+
shufffle [options]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
**OPTIONS**
|
|
14
|
+
|
|
15
|
+
-c, --config <path> Path to config file (default: ./proxy.config.json)
|
|
16
|
+
-l, --log-level <level> Log level: debug | info | warn | error | silent (default: info)
|
|
17
|
+
-e, --env <key=value> Set environment variables (can be used multiple times). Variables already present
|
|
18
|
+
in process.env are also honored. .env files are not loaded automatically — use a
|
|
19
|
+
loader (e.g. \`node --env-file=.env\`) if you want that behavior.
|
|
20
|
+
-b, --balancer <name> Load balancer strategy: round-robin | random | weighted (overrides config)
|
|
21
|
+
-h, --help Show this help message
|
|
22
|
+
|
|
23
|
+
**CONFIG FORMAT**
|
|
24
|
+
|
|
25
|
+
DEFAULT CONFIG: proxy.config.json
|
|
26
|
+
|
|
27
|
+
{
|
|
28
|
+
"port": 8080,
|
|
29
|
+
"balancer": "round-robin",
|
|
30
|
+
"headers": {
|
|
31
|
+
"response": { "X-Powered-By": "shufffle" }
|
|
32
|
+
},
|
|
33
|
+
"routes": [
|
|
34
|
+
{
|
|
35
|
+
"match": "/api",
|
|
36
|
+
"rewrite": { "stripPrefix": "/api" },
|
|
37
|
+
"upstreams": [
|
|
38
|
+
{ "host": "localhost", "port": 3001 },
|
|
39
|
+
{ "host": "localhost", "port": 3002 }
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"match": "/",
|
|
44
|
+
"upstreams": [{ "host": "localhost", "port": 3000 }]
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
**EXAMPLES**
|
|
50
|
+
|
|
51
|
+
shufffle
|
|
52
|
+
shufffle --config ./config/dev.json --log-level debug
|
|
53
|
+
`);
|
|
54
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function main(): Promise<void>;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.main = main;
|
|
8
|
+
const node_process_1 = __importDefault(require("node:process"));
|
|
9
|
+
const config_js_1 = require("../config/config.js");
|
|
10
|
+
const env_overrides_js_1 = require("../env-overrides.js");
|
|
11
|
+
const proxy_server_js_1 = require("../lib/services/proxy/proxy-server.js");
|
|
12
|
+
const logger_js_1 = require("../logger/logger.js");
|
|
13
|
+
const help_js_1 = require("./help.js");
|
|
14
|
+
const parse_args_js_1 = require("./parse-args.js");
|
|
15
|
+
async function main() {
|
|
16
|
+
const { configPath, logLevel, help, env, balancer } = (0, parse_args_js_1.parseArgs)(node_process_1.default.argv);
|
|
17
|
+
if (help) {
|
|
18
|
+
(0, help_js_1.printHelp)();
|
|
19
|
+
node_process_1.default.exit(0);
|
|
20
|
+
}
|
|
21
|
+
for (const [k, v] of Object.entries(env)) {
|
|
22
|
+
node_process_1.default.env[k] = v;
|
|
23
|
+
}
|
|
24
|
+
const logger = new logger_js_1.Logger(logLevel);
|
|
25
|
+
let config;
|
|
26
|
+
try {
|
|
27
|
+
const loaded = await config_js_1.Config.fromFile(configPath);
|
|
28
|
+
config = (0, env_overrides_js_1.applyEnvOverrides)({ ...loaded }, (0, env_overrides_js_1.envOverrides)());
|
|
29
|
+
if (balancer)
|
|
30
|
+
config = { ...config, balancer };
|
|
31
|
+
logger.debug(`Config loaded from ${configPath}:`, { config: configPath });
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
logger.error(`Failed to load config from ${configPath}:`, {
|
|
35
|
+
error: err instanceof Error ? err.message : String(err),
|
|
36
|
+
});
|
|
37
|
+
node_process_1.default.exit(1);
|
|
38
|
+
}
|
|
39
|
+
const server = new proxy_server_js_1.ProxyServer(config, {
|
|
40
|
+
onRequest({ req, upstream, targetPath }) {
|
|
41
|
+
logger.debug('→ request', {
|
|
42
|
+
method: req.method,
|
|
43
|
+
url: req.url,
|
|
44
|
+
upstream: `${upstream.host}:${upstream.port}`,
|
|
45
|
+
path: targetPath,
|
|
46
|
+
});
|
|
47
|
+
return true;
|
|
48
|
+
},
|
|
49
|
+
onResponse(ctx, statusCode) {
|
|
50
|
+
logger.debug('← response', {
|
|
51
|
+
statusCode,
|
|
52
|
+
url: ctx.req.url,
|
|
53
|
+
method: ctx.req.method,
|
|
54
|
+
upstream: `${ctx.upstream.host}:${ctx.upstream.port}`,
|
|
55
|
+
path: ctx.targetPath,
|
|
56
|
+
});
|
|
57
|
+
},
|
|
58
|
+
onError(error, ctx) {
|
|
59
|
+
logger.error('✗✗✗ proxy error ✗✗✗', {
|
|
60
|
+
error: error.message,
|
|
61
|
+
url: ctx?.req?.url,
|
|
62
|
+
method: ctx?.req?.method,
|
|
63
|
+
upstream: ctx?.upstream
|
|
64
|
+
? `${ctx.upstream.host}:${ctx.upstream.port}`
|
|
65
|
+
: undefined,
|
|
66
|
+
path: ctx?.targetPath,
|
|
67
|
+
});
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
await server.listen();
|
|
71
|
+
logger.debug(`Proxy server is listening on ${config.host ?? ''}:${config.port}`, {
|
|
72
|
+
port: config.port,
|
|
73
|
+
host: config.host ?? '0.0.0.0',
|
|
74
|
+
routes: config.routes.length,
|
|
75
|
+
});
|
|
76
|
+
for (const sig of ['SIGINT', 'SIGTERM', 'SIGQUIT']) {
|
|
77
|
+
node_process_1.default.on(sig, async () => {
|
|
78
|
+
logger.debug(`✗✗✗ Shut Down Mode ✗✗✗\nReceived ${sig}, Commencing shut down!`, { signal: sig });
|
|
79
|
+
try {
|
|
80
|
+
await server.close();
|
|
81
|
+
logger.debug('✗✗✗ Graceful shutdown bye ✗✗✗');
|
|
82
|
+
node_process_1.default.exit(0);
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
logger.error('✗✗✗ Error during shutdown; what do you think mopopipo ✗✗✗', {
|
|
86
|
+
error: err instanceof Error ? err.message : String(err),
|
|
87
|
+
});
|
|
88
|
+
node_process_1.default.exit(1);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
main().catch((err) => {
|
|
94
|
+
console.error('✗✗✗ Fatal error ✗✗✗', err instanceof Error ? err.message : String(err));
|
|
95
|
+
node_process_1.default.exit(1);
|
|
96
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { LoadBalancerStrategy } from '../lib/types/load-balancer-strategy.js';
|
|
2
|
+
import type { LogLevel } from '../lib/types/log.js';
|
|
3
|
+
export declare function parseArgs(argv: string[]): {
|
|
4
|
+
configPath: string;
|
|
5
|
+
logLevel: LogLevel;
|
|
6
|
+
help: boolean;
|
|
7
|
+
env: Record<string, string>;
|
|
8
|
+
balancer?: LoadBalancerStrategy;
|
|
9
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseArgs = parseArgs;
|
|
4
|
+
const load_balancer_strategy_js_1 = require("../lib/types/load-balancer-strategy.js");
|
|
5
|
+
const log_js_1 = require("../lib/types/log.js");
|
|
6
|
+
function parseArgs(argv) {
|
|
7
|
+
const args = argv.slice(2);
|
|
8
|
+
let configPath = './proxy.config.json';
|
|
9
|
+
let logLevel = 'info';
|
|
10
|
+
let help = false;
|
|
11
|
+
const env = {};
|
|
12
|
+
let balancer;
|
|
13
|
+
for (let i = 0; i < args.length; i++) {
|
|
14
|
+
const arg = args[i];
|
|
15
|
+
switch (arg) {
|
|
16
|
+
case '--help':
|
|
17
|
+
case '-h':
|
|
18
|
+
help = true;
|
|
19
|
+
break;
|
|
20
|
+
case '--config':
|
|
21
|
+
case '-c':
|
|
22
|
+
if (i + 1 >= args.length)
|
|
23
|
+
throw new Error(`Missing value for ${arg}`);
|
|
24
|
+
configPath = args[++i];
|
|
25
|
+
break;
|
|
26
|
+
case '--log-level':
|
|
27
|
+
case '-l': {
|
|
28
|
+
if (i + 1 >= args.length)
|
|
29
|
+
throw new Error(`Missing value for ${arg}`);
|
|
30
|
+
const value = args[++i];
|
|
31
|
+
const valid = Object.keys(log_js_1.LEVELS);
|
|
32
|
+
if (!valid.includes(value)) {
|
|
33
|
+
throw new Error(`Invalid value for ${arg}: ${value}. Must be one of: ${valid.join(', ')}`);
|
|
34
|
+
}
|
|
35
|
+
logLevel = value;
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
case '--env':
|
|
39
|
+
case '-e': {
|
|
40
|
+
if (i + 1 >= args.length)
|
|
41
|
+
throw new Error(`Missing value for ${arg}`);
|
|
42
|
+
const raw = args[++i];
|
|
43
|
+
const eq = raw.indexOf('=');
|
|
44
|
+
if (eq <= 0)
|
|
45
|
+
throw new Error(`Invalid value for ${arg}: ${raw}`);
|
|
46
|
+
const key = raw.slice(0, eq);
|
|
47
|
+
const value = raw.slice(eq + 1);
|
|
48
|
+
env[key] = value;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
case '--balancer':
|
|
52
|
+
case '-b': {
|
|
53
|
+
if (i + 1 >= args.length)
|
|
54
|
+
throw new Error(`Missing value for ${arg}`);
|
|
55
|
+
const value = args[++i];
|
|
56
|
+
const valid = Object.values(load_balancer_strategy_js_1.LoadBalancerStrategy);
|
|
57
|
+
if (!valid.includes(value)) {
|
|
58
|
+
throw new Error(`Invalid value for ${arg}: ${value}. Must be one of: ${valid.join(', ')}`);
|
|
59
|
+
}
|
|
60
|
+
balancer = value;
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
default:
|
|
64
|
+
throw new Error(`Unknown argument: ${arg}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return { configPath, logLevel, help, env, balancer };
|
|
68
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ConfigType } from '../lib/types/config.js';
|
|
2
|
+
export declare class Config {
|
|
3
|
+
readonly port: number;
|
|
4
|
+
readonly host: string;
|
|
5
|
+
readonly routes: ConfigType['routes'];
|
|
6
|
+
readonly headers?: ConfigType['headers'];
|
|
7
|
+
readonly balancer?: ConfigType['balancer'];
|
|
8
|
+
readonly timeout?: ConfigType['timeout'];
|
|
9
|
+
readonly forwardIp?: ConfigType['forwardIp'];
|
|
10
|
+
readonly maxBodySize?: ConfigType['maxBodySize'];
|
|
11
|
+
readonly healthCheck?: ConfigType['healthCheck'];
|
|
12
|
+
private constructor();
|
|
13
|
+
static validate(raw: unknown, source: string): ConfigType;
|
|
14
|
+
static fromFile(filePath: string): Promise<Config>;
|
|
15
|
+
static fromObject(data: unknown, source?: string): Config;
|
|
16
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.Config = void 0;
|
|
40
|
+
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
41
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
42
|
+
const node_url_1 = require("node:url");
|
|
43
|
+
const load_balancer_strategy_js_1 = require("../lib/types/load-balancer-strategy.js");
|
|
44
|
+
const VALID_BALANCERS = new Set(Object.values(load_balancer_strategy_js_1.LoadBalancerStrategy));
|
|
45
|
+
const VALID_PROTOCOLS = new Set(['http', 'https']);
|
|
46
|
+
function isPositiveInt(v) {
|
|
47
|
+
return typeof v === 'number' && Number.isInteger(v) && v > 0;
|
|
48
|
+
}
|
|
49
|
+
function isNonNegativeInt(v) {
|
|
50
|
+
return typeof v === 'number' && Number.isInteger(v) && v >= 0;
|
|
51
|
+
}
|
|
52
|
+
class Config {
|
|
53
|
+
port;
|
|
54
|
+
host;
|
|
55
|
+
routes;
|
|
56
|
+
headers;
|
|
57
|
+
balancer;
|
|
58
|
+
timeout;
|
|
59
|
+
forwardIp;
|
|
60
|
+
maxBodySize;
|
|
61
|
+
healthCheck;
|
|
62
|
+
constructor(cfg) {
|
|
63
|
+
this.port = cfg.port;
|
|
64
|
+
this.host = cfg.host ?? '0.0.0.0';
|
|
65
|
+
this.routes = cfg.routes;
|
|
66
|
+
this.headers = cfg.headers;
|
|
67
|
+
this.balancer = cfg.balancer;
|
|
68
|
+
this.timeout = cfg.timeout;
|
|
69
|
+
this.forwardIp = cfg.forwardIp;
|
|
70
|
+
this.maxBodySize = cfg.maxBodySize;
|
|
71
|
+
this.healthCheck = cfg.healthCheck;
|
|
72
|
+
}
|
|
73
|
+
static validate(raw, source) {
|
|
74
|
+
if (!raw || typeof raw !== 'object') {
|
|
75
|
+
throw new Error(`Config in source ${source} must be an object`);
|
|
76
|
+
}
|
|
77
|
+
const conf = raw;
|
|
78
|
+
if (typeof conf.port !== 'number') {
|
|
79
|
+
throw new Error(`Config in ${source} must have a numeric 'port' property`);
|
|
80
|
+
}
|
|
81
|
+
if (conf.port < 1 || conf.port > 65535 || !Number.isInteger(conf.port)) {
|
|
82
|
+
throw new Error(`Config in ${source} PORT must be an integer between 1 and 65535.`);
|
|
83
|
+
}
|
|
84
|
+
if (conf.host !== undefined) {
|
|
85
|
+
if (typeof conf.host !== 'string' || conf.host.length === 0) {
|
|
86
|
+
throw new Error(`Config in ${source} 'host' must be a non-empty string`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (conf.balancer !== undefined && !VALID_BALANCERS.has(conf.balancer)) {
|
|
90
|
+
throw new Error(`Config in ${source} 'balancer' must be one of ${[...VALID_BALANCERS].join(', ')}, got '${conf.balancer}'`);
|
|
91
|
+
}
|
|
92
|
+
if (conf.timeout !== undefined && !isPositiveInt(conf.timeout)) {
|
|
93
|
+
throw new Error(`Config in ${source} 'timeout' must be a positive integer (ms)`);
|
|
94
|
+
}
|
|
95
|
+
if (conf.forwardIp !== undefined && typeof conf.forwardIp !== 'boolean') {
|
|
96
|
+
throw new Error(`Config in ${source} 'forwardIp' must be a boolean`);
|
|
97
|
+
}
|
|
98
|
+
if (conf.maxBodySize !== undefined && !isNonNegativeInt(conf.maxBodySize)) {
|
|
99
|
+
throw new Error(`Config in ${source} 'maxBodySize' must be a non-negative integer (bytes)`);
|
|
100
|
+
}
|
|
101
|
+
if (conf.healthCheck !== undefined) {
|
|
102
|
+
if (typeof conf.healthCheck !== 'object' || conf.healthCheck === null) {
|
|
103
|
+
throw new Error(`Config in ${source} 'healthCheck' must be an object`);
|
|
104
|
+
}
|
|
105
|
+
const { interval, timeout } = conf.healthCheck;
|
|
106
|
+
if (interval !== undefined && !isPositiveInt(interval)) {
|
|
107
|
+
throw new Error(`Config in ${source} 'healthCheck.interval' must be a positive integer (ms)`);
|
|
108
|
+
}
|
|
109
|
+
if (timeout !== undefined && !isPositiveInt(timeout)) {
|
|
110
|
+
throw new Error(`Config in ${source} 'healthCheck.timeout' must be a positive integer (ms)`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (!Array.isArray(conf.routes) || conf.routes.length === 0) {
|
|
114
|
+
throw new Error(`Config in ${source} must have a non-empty 'routes' array`);
|
|
115
|
+
}
|
|
116
|
+
for (const [i, rte] of conf.routes.entries()) {
|
|
117
|
+
if (rte.match === undefined || rte.match === null) {
|
|
118
|
+
throw new Error(`Config in ${source} is required to have routes.match at index ${i}`);
|
|
119
|
+
}
|
|
120
|
+
if (typeof rte.match !== 'string' && typeof rte.match !== 'function') {
|
|
121
|
+
throw new Error(`Config in ${source} routes.match at index ${i} must be a string or function, got ${typeof rte.match}`);
|
|
122
|
+
}
|
|
123
|
+
if (!Array.isArray(rte.upstreams) || rte.upstreams.length === 0) {
|
|
124
|
+
throw new Error(`Config in ${source} is required to have routes.upstreams at index ${i}`);
|
|
125
|
+
}
|
|
126
|
+
for (const [j, u] of rte.upstreams.entries()) {
|
|
127
|
+
if (typeof u.host !== 'string' || u.host.length === 0) {
|
|
128
|
+
throw new Error(`Config in ${source} routes[${i}].upstreams[${j}].host must be a non-empty string`);
|
|
129
|
+
}
|
|
130
|
+
if (typeof u.port !== 'number') {
|
|
131
|
+
throw new Error(`Config in ${source} routes[${i}].upstreams[${j}].port must be a number`);
|
|
132
|
+
}
|
|
133
|
+
if (u.port < 1 || u.port > 65535 || !Number.isInteger(u.port)) {
|
|
134
|
+
throw new Error(`Config in ${source} upstream port must be an integer between 1 and 65535.`);
|
|
135
|
+
}
|
|
136
|
+
if (u.protocol !== undefined && !VALID_PROTOCOLS.has(u.protocol)) {
|
|
137
|
+
throw new Error(`Config in ${source} routes[${i}].upstreams[${j}].protocol must be 'http' or 'https', got '${u.protocol}'`);
|
|
138
|
+
}
|
|
139
|
+
if (u.weight !== undefined &&
|
|
140
|
+
(typeof u.weight !== 'number' ||
|
|
141
|
+
!Number.isFinite(u.weight) ||
|
|
142
|
+
u.weight <= 0)) {
|
|
143
|
+
throw new Error(`Config in ${source} routes[${i}].upstreams[${j}].weight must be a positive number`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (rte.balancer !== undefined && !VALID_BALANCERS.has(rte.balancer)) {
|
|
147
|
+
throw new Error(`Config in ${source} routes[${i}].balancer must be one of ${[...VALID_BALANCERS].join(', ')}, got '${rte.balancer}'`);
|
|
148
|
+
}
|
|
149
|
+
if (rte.timeout !== undefined && !isPositiveInt(rte.timeout)) {
|
|
150
|
+
throw new Error(`Config in ${source} routes[${i}].timeout must be a positive integer (ms)`);
|
|
151
|
+
}
|
|
152
|
+
if (rte.maxBodySize !== undefined && !isNonNegativeInt(rte.maxBodySize)) {
|
|
153
|
+
throw new Error(`Config in ${source} routes[${i}].maxBodySize must be a non-negative integer (bytes)`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return conf;
|
|
157
|
+
}
|
|
158
|
+
static async fromFile(filePath) {
|
|
159
|
+
const absolutePath = node_path_1.default.resolve(filePath);
|
|
160
|
+
const extension = node_path_1.default.extname(absolutePath).toLowerCase();
|
|
161
|
+
let raw;
|
|
162
|
+
if (extension === '.json') {
|
|
163
|
+
const contents = await promises_1.default.readFile(absolutePath, 'utf-8');
|
|
164
|
+
raw = JSON.parse(contents);
|
|
165
|
+
}
|
|
166
|
+
else if (extension === '.js' ||
|
|
167
|
+
extension === '.mjs' ||
|
|
168
|
+
extension === '.cjs') {
|
|
169
|
+
const module = (await Promise.resolve(`${(0, node_url_1.pathToFileURL)(absolutePath).href}`).then(s => __importStar(require(s))));
|
|
170
|
+
raw = module.default ?? module;
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
throw new Error(`Unsupported config file extension: ${extension}. Supported: .json, .js, .mjs, .cjs. ` +
|
|
174
|
+
`For TypeScript configs, compile to JavaScript first or run via a TS-aware runtime.`);
|
|
175
|
+
}
|
|
176
|
+
const validated = Config.validate(raw, filePath);
|
|
177
|
+
return new Config(validated);
|
|
178
|
+
}
|
|
179
|
+
static fromObject(data, source = 'inline') {
|
|
180
|
+
const validated = Config.validate(data, source);
|
|
181
|
+
return new Config(validated);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
exports.Config = Config;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ConfigType } from './lib/types/config.js';
|
|
2
|
+
export interface EnvOverrides {
|
|
3
|
+
host?: string;
|
|
4
|
+
port?: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function envOverrides(): EnvOverrides;
|
|
7
|
+
export declare function applyEnvOverrides(config: ConfigType, overrides: EnvOverrides): ConfigType;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.envOverrides = envOverrides;
|
|
4
|
+
exports.applyEnvOverrides = applyEnvOverrides;
|
|
5
|
+
function envOverrides() {
|
|
6
|
+
const overrides = {};
|
|
7
|
+
const warnings = [];
|
|
8
|
+
const rawPort = process.env.PORT;
|
|
9
|
+
if (rawPort !== undefined) {
|
|
10
|
+
const trimmed = rawPort.trim();
|
|
11
|
+
const parsed = /^\d+$/.test(trimmed) ? Number(trimmed) : Number.NaN;
|
|
12
|
+
if (!Number.isInteger(parsed) || parsed < 1 || parsed > 65535) {
|
|
13
|
+
warnings.push(`PORT value must be an integer between 1 - 65535.\nRun picked up ${rawPort}`);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
overrides.port = parsed;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const rawHost = process.env.HOST;
|
|
20
|
+
if (rawHost !== undefined) {
|
|
21
|
+
if (rawHost.trim() === '') {
|
|
22
|
+
warnings.push(`HOST value cannot be empty.\nRun picked up ${rawHost}`);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
overrides.host = rawHost.trim();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
for (const w of warnings) {
|
|
29
|
+
process.stdout.write(`--- [shufffle] WARNING --- ${w}\n`);
|
|
30
|
+
}
|
|
31
|
+
return overrides;
|
|
32
|
+
}
|
|
33
|
+
function applyEnvOverrides(config, overrides) {
|
|
34
|
+
if (Object.keys(overrides).length === 0)
|
|
35
|
+
return config;
|
|
36
|
+
return { ...config, ...overrides };
|
|
37
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { Config } from './config/config.js';
|
|
2
|
+
export { createProxy, ProxyServer } from './lib/services/proxy/proxy-server.js';
|
|
3
|
+
export type { ConfigType } from './lib/types/config.js';
|
|
4
|
+
export type { Context } from './lib/types/context.js';
|
|
5
|
+
export type { HeaderRules } from './lib/types/header-rules.js';
|
|
6
|
+
export type { Hooks } from './lib/types/hooks.js';
|
|
7
|
+
export { LoadBalancerStrategy } from './lib/types/load-balancer-strategy.js';
|
|
8
|
+
export type { Route } from './lib/types/route.js';
|
|
9
|
+
export type { RouteRewrite } from './lib/types/route-rewrite.js';
|
|
10
|
+
export type { Upstream } from './lib/types/upstream.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LoadBalancerStrategy = exports.ProxyServer = exports.createProxy = exports.Config = void 0;
|
|
4
|
+
var config_js_1 = require("./config/config.js");
|
|
5
|
+
Object.defineProperty(exports, "Config", { enumerable: true, get: function () { return config_js_1.Config; } });
|
|
6
|
+
var proxy_server_js_1 = require("./lib/services/proxy/proxy-server.js");
|
|
7
|
+
Object.defineProperty(exports, "createProxy", { enumerable: true, get: function () { return proxy_server_js_1.createProxy; } });
|
|
8
|
+
Object.defineProperty(exports, "ProxyServer", { enumerable: true, get: function () { return proxy_server_js_1.ProxyServer; } });
|
|
9
|
+
var load_balancer_strategy_js_1 = require("./lib/types/load-balancer-strategy.js");
|
|
10
|
+
Object.defineProperty(exports, "LoadBalancerStrategy", { enumerable: true, get: function () { return load_balancer_strategy_js_1.LoadBalancerStrategy; } });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const HOP_BY_HOP_HEADERS: Set<string>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HOP_BY_HOP_HEADERS = void 0;
|
|
4
|
+
exports.HOP_BY_HOP_HEADERS = new Set([
|
|
5
|
+
'connection',
|
|
6
|
+
'keep-alive',
|
|
7
|
+
'proxy-authenticate',
|
|
8
|
+
'proxy-authorization',
|
|
9
|
+
'te',
|
|
10
|
+
'trailer',
|
|
11
|
+
'transfer-encoding',
|
|
12
|
+
'upgrade',
|
|
13
|
+
]);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import { Logger } from '../../../logger/logger.js';
|
|
3
|
+
import type { ConfigType } from '../../types/config.js';
|
|
4
|
+
import type { Hooks } from '../../types/hooks.js';
|
|
5
|
+
import { LoadBalancerStrategy } from '../../types/load-balancer-strategy.js';
|
|
6
|
+
import type { Upstream } from '../../types/upstream.js';
|
|
7
|
+
import { HeadersService } from '../headers/headers-service.js';
|
|
8
|
+
import type { LoadBalancer } from '../load-balancers/load-balancer.js';
|
|
9
|
+
export declare class HttpHandler {
|
|
10
|
+
readonly config: ConfigType;
|
|
11
|
+
private readonly hooks;
|
|
12
|
+
private readonly balancers;
|
|
13
|
+
private readonly globalBalancer;
|
|
14
|
+
private readonly httpAgent;
|
|
15
|
+
private readonly httpsAgent;
|
|
16
|
+
private readonly healthService;
|
|
17
|
+
private readonly headersService;
|
|
18
|
+
private readonly logger;
|
|
19
|
+
constructor(config: ConfigType, hooks?: Hooks, headersService?: HeadersService, logger?: Logger);
|
|
20
|
+
start(): void;
|
|
21
|
+
stop(): void;
|
|
22
|
+
handler(req: IncomingMessage, res: ServerResponse): Promise<void>;
|
|
23
|
+
private forward;
|
|
24
|
+
private canRetry;
|
|
25
|
+
healthyCandidates(upstreams: Upstream[]): Upstream[];
|
|
26
|
+
getBalancer(route: {
|
|
27
|
+
upstreams: Upstream[];
|
|
28
|
+
balancer?: LoadBalancerStrategy;
|
|
29
|
+
}): LoadBalancer;
|
|
30
|
+
private handleError;
|
|
31
|
+
private sendError;
|
|
32
|
+
}
|