@push.rocks/smartproxy 12.0.0 → 13.1.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/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/certificate/acme/acme-factory.d.ts +17 -0
- package/dist_ts/certificate/acme/acme-factory.js +40 -0
- package/dist_ts/certificate/acme/challenge-handler.d.ts +44 -0
- package/dist_ts/certificate/acme/challenge-handler.js +92 -0
- package/dist_ts/certificate/acme/index.d.ts +4 -0
- package/dist_ts/certificate/acme/index.js +5 -0
- package/dist_ts/certificate/events/certificate-events.d.ts +33 -0
- package/dist_ts/certificate/events/certificate-events.js +38 -0
- package/dist_ts/certificate/index.d.ts +24 -0
- package/dist_ts/certificate/index.js +39 -0
- package/dist_ts/certificate/models/certificate-types.d.ts +77 -0
- package/dist_ts/certificate/models/certificate-types.js +2 -0
- package/dist_ts/certificate/providers/cert-provisioner.d.ts +93 -0
- package/dist_ts/certificate/providers/cert-provisioner.js +262 -0
- package/dist_ts/certificate/providers/index.d.ts +4 -0
- package/dist_ts/certificate/providers/index.js +5 -0
- package/dist_ts/certificate/storage/file-storage.d.ts +66 -0
- package/dist_ts/certificate/storage/file-storage.js +194 -0
- package/dist_ts/certificate/storage/index.d.ts +4 -0
- package/dist_ts/certificate/storage/index.js +5 -0
- package/dist_ts/certificate/utils/certificate-helpers.d.ts +17 -0
- package/dist_ts/certificate/utils/certificate-helpers.js +45 -0
- package/dist_ts/common/eventUtils.d.ts +1 -1
- package/dist_ts/common/port80-adapter.d.ts +1 -1
- package/dist_ts/core/events/index.d.ts +4 -0
- package/dist_ts/core/events/index.js +5 -0
- package/dist_ts/core/index.d.ts +6 -0
- package/dist_ts/core/index.js +8 -0
- package/dist_ts/core/models/common-types.d.ts +82 -0
- package/dist_ts/core/models/common-types.js +15 -0
- package/dist_ts/core/models/index.d.ts +4 -0
- package/dist_ts/core/models/index.js +5 -0
- package/dist_ts/core/utils/event-utils.d.ts +15 -0
- package/dist_ts/core/utils/event-utils.js +19 -0
- package/dist_ts/core/utils/index.d.ts +6 -0
- package/dist_ts/core/utils/index.js +7 -0
- package/dist_ts/core/utils/ip-utils.d.ts +53 -0
- package/dist_ts/core/utils/ip-utils.js +153 -0
- package/dist_ts/core/utils/validation-utils.d.ts +61 -0
- package/dist_ts/core/utils/validation-utils.js +149 -0
- package/dist_ts/forwarding/config/domain-config.d.ts +12 -0
- package/dist_ts/forwarding/config/domain-config.js +12 -0
- package/dist_ts/forwarding/config/domain-manager.d.ts +86 -0
- package/dist_ts/forwarding/config/domain-manager.js +242 -0
- package/dist_ts/forwarding/config/forwarding-types.d.ts +104 -0
- package/dist_ts/forwarding/config/forwarding-types.js +50 -0
- package/dist_ts/forwarding/config/index.d.ts +6 -0
- package/dist_ts/forwarding/config/index.js +7 -0
- package/dist_ts/forwarding/factory/forwarding-factory.d.ts +25 -0
- package/dist_ts/forwarding/factory/forwarding-factory.js +138 -0
- package/dist_ts/forwarding/factory/index.d.ts +4 -0
- package/dist_ts/forwarding/factory/index.js +5 -0
- package/dist_ts/forwarding/handlers/base-handler.d.ts +55 -0
- package/dist_ts/forwarding/handlers/base-handler.js +94 -0
- package/dist_ts/forwarding/handlers/http-handler.d.ts +30 -0
- package/dist_ts/forwarding/handlers/http-handler.js +131 -0
- package/dist_ts/forwarding/handlers/https-passthrough-handler.d.ts +29 -0
- package/dist_ts/forwarding/handlers/https-passthrough-handler.js +162 -0
- package/dist_ts/forwarding/handlers/https-terminate-to-http-handler.d.ts +36 -0
- package/dist_ts/forwarding/handlers/https-terminate-to-http-handler.js +229 -0
- package/dist_ts/forwarding/handlers/https-terminate-to-https-handler.d.ts +35 -0
- package/dist_ts/forwarding/handlers/https-terminate-to-https-handler.js +254 -0
- package/dist_ts/forwarding/handlers/index.d.ts +8 -0
- package/dist_ts/forwarding/handlers/index.js +9 -0
- package/dist_ts/forwarding/index.d.ts +19 -0
- package/dist_ts/forwarding/index.js +25 -0
- package/dist_ts/http/index.d.ts +15 -0
- package/dist_ts/http/index.js +20 -0
- package/dist_ts/http/models/http-types.d.ts +81 -0
- package/dist_ts/http/models/http-types.js +62 -0
- package/dist_ts/http/port80/acme-interfaces.d.ts +78 -0
- package/dist_ts/http/port80/acme-interfaces.js +6 -0
- package/dist_ts/http/port80/challenge-responder.d.ts +53 -0
- package/dist_ts/http/port80/challenge-responder.js +203 -0
- package/dist_ts/http/port80/index.d.ts +6 -0
- package/dist_ts/http/port80/index.js +9 -0
- package/dist_ts/http/port80/port80-handler.d.ts +121 -0
- package/dist_ts/http/port80/port80-handler.js +554 -0
- package/dist_ts/http/redirects/index.d.ts +4 -0
- package/dist_ts/http/redirects/index.js +5 -0
- package/dist_ts/http/router/index.d.ts +4 -0
- package/dist_ts/http/router/index.js +5 -0
- package/dist_ts/http/router/proxy-router.d.ts +115 -0
- package/dist_ts/http/router/proxy-router.js +325 -0
- package/dist_ts/index.d.ts +15 -8
- package/dist_ts/index.js +26 -10
- package/dist_ts/networkproxy/classes.np.certificatemanager.js +2 -2
- package/dist_ts/networkproxy/index.d.ts +1 -6
- package/dist_ts/networkproxy/index.js +4 -8
- package/dist_ts/plugins.d.ts +2 -1
- package/dist_ts/plugins.js +3 -2
- package/dist_ts/port80handler/classes.port80handler.d.ts +8 -136
- package/dist_ts/port80handler/classes.port80handler.js +14 -567
- package/dist_ts/proxies/index.d.ts +6 -0
- package/dist_ts/proxies/index.js +8 -0
- package/dist_ts/proxies/network-proxy/certificate-manager.d.ts +77 -0
- package/dist_ts/proxies/network-proxy/certificate-manager.js +373 -0
- package/dist_ts/proxies/network-proxy/connection-pool.d.ts +47 -0
- package/dist_ts/proxies/network-proxy/connection-pool.js +210 -0
- package/dist_ts/proxies/network-proxy/index.d.ts +10 -0
- package/dist_ts/proxies/network-proxy/index.js +12 -0
- package/dist_ts/proxies/network-proxy/models/index.d.ts +4 -0
- package/dist_ts/proxies/network-proxy/models/index.js +5 -0
- package/dist_ts/proxies/network-proxy/models/types.d.ts +80 -0
- package/dist_ts/proxies/network-proxy/models/types.js +35 -0
- package/dist_ts/proxies/network-proxy/network-proxy.d.ts +118 -0
- package/dist_ts/proxies/network-proxy/network-proxy.js +387 -0
- package/dist_ts/proxies/network-proxy/request-handler.d.ts +57 -0
- package/dist_ts/proxies/network-proxy/request-handler.js +394 -0
- package/dist_ts/proxies/network-proxy/websocket-handler.d.ts +38 -0
- package/dist_ts/proxies/network-proxy/websocket-handler.js +188 -0
- package/dist_ts/proxies/nftables-proxy/index.d.ts +5 -0
- package/dist_ts/proxies/nftables-proxy/index.js +6 -0
- package/dist_ts/proxies/nftables-proxy/models/errors.d.ts +15 -0
- package/dist_ts/proxies/nftables-proxy/models/errors.js +28 -0
- package/dist_ts/proxies/nftables-proxy/models/index.d.ts +5 -0
- package/dist_ts/proxies/nftables-proxy/models/index.js +6 -0
- package/dist_ts/proxies/nftables-proxy/models/interfaces.d.ts +75 -0
- package/dist_ts/proxies/nftables-proxy/models/interfaces.js +5 -0
- package/dist_ts/proxies/nftables-proxy/nftables-proxy.d.ts +136 -0
- package/dist_ts/proxies/nftables-proxy/nftables-proxy.js +1516 -0
- package/dist_ts/proxies/smart-proxy/connection-handler.d.ts +39 -0
- package/dist_ts/proxies/smart-proxy/connection-handler.js +894 -0
- package/dist_ts/proxies/smart-proxy/connection-manager.d.ts +78 -0
- package/dist_ts/proxies/smart-proxy/connection-manager.js +378 -0
- package/dist_ts/proxies/smart-proxy/domain-config-manager.d.ts +95 -0
- package/dist_ts/proxies/smart-proxy/domain-config-manager.js +255 -0
- package/dist_ts/proxies/smart-proxy/index.d.ts +13 -0
- package/dist_ts/proxies/smart-proxy/index.js +17 -0
- package/dist_ts/proxies/smart-proxy/models/index.d.ts +4 -0
- package/dist_ts/proxies/smart-proxy/models/index.js +5 -0
- package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +107 -0
- package/dist_ts/proxies/smart-proxy/models/interfaces.js +2 -0
- package/dist_ts/proxies/smart-proxy/network-proxy-bridge.d.ts +62 -0
- package/dist_ts/proxies/smart-proxy/network-proxy-bridge.js +316 -0
- package/dist_ts/proxies/smart-proxy/port-range-manager.d.ts +56 -0
- package/dist_ts/proxies/smart-proxy/port-range-manager.js +176 -0
- package/dist_ts/proxies/smart-proxy/security-manager.d.ts +64 -0
- package/dist_ts/proxies/smart-proxy/security-manager.js +149 -0
- package/dist_ts/proxies/smart-proxy/smart-proxy.d.ts +63 -0
- package/dist_ts/proxies/smart-proxy/smart-proxy.js +523 -0
- package/dist_ts/proxies/smart-proxy/timeout-manager.d.ts +47 -0
- package/dist_ts/proxies/smart-proxy/timeout-manager.js +154 -0
- package/dist_ts/proxies/smart-proxy/tls-manager.d.ts +57 -0
- package/dist_ts/proxies/smart-proxy/tls-manager.js +132 -0
- package/dist_ts/smartproxy/classes.pp.networkproxybridge.d.ts +2 -2
- package/dist_ts/smartproxy/classes.pp.networkproxybridge.js +1 -1
- package/dist_ts/smartproxy/classes.pp.tlsmanager.js +2 -2
- package/dist_ts/smartproxy/classes.smartproxy.js +3 -3
- package/dist_ts/tls/alerts/index.d.ts +4 -0
- package/dist_ts/tls/alerts/index.js +5 -0
- package/dist_ts/tls/alerts/tls-alert.d.ts +150 -0
- package/dist_ts/tls/alerts/tls-alert.js +226 -0
- package/dist_ts/tls/index.d.ts +18 -0
- package/dist_ts/tls/index.js +27 -0
- package/dist_ts/tls/sni/client-hello-parser.d.ts +100 -0
- package/dist_ts/tls/sni/client-hello-parser.js +463 -0
- package/dist_ts/tls/sni/index.d.ts +4 -0
- package/dist_ts/tls/sni/index.js +5 -0
- package/dist_ts/tls/sni/sni-extraction.d.ts +58 -0
- package/dist_ts/tls/sni/sni-extraction.js +275 -0
- package/dist_ts/tls/sni/sni-handler.d.ts +154 -0
- package/dist_ts/tls/sni/sni-handler.js +191 -0
- package/dist_ts/tls/utils/index.d.ts +4 -0
- package/dist_ts/tls/utils/index.js +5 -0
- package/dist_ts/tls/utils/tls-utils.d.ts +158 -0
- package/dist_ts/tls/utils/tls-utils.js +187 -0
- package/package.json +1 -1
- package/readme.md +89 -21
- package/readme.plan.md +253 -469
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/certificate/acme/acme-factory.ts +48 -0
- package/ts/certificate/acme/challenge-handler.ts +110 -0
- package/ts/certificate/acme/index.ts +3 -0
- package/ts/certificate/events/certificate-events.ts +36 -0
- package/ts/certificate/index.ts +67 -0
- package/ts/certificate/models/certificate-types.ts +88 -0
- package/ts/certificate/providers/cert-provisioner.ts +326 -0
- package/ts/certificate/providers/index.ts +3 -0
- package/ts/certificate/storage/file-storage.ts +234 -0
- package/ts/certificate/storage/index.ts +3 -0
- package/ts/certificate/utils/certificate-helpers.ts +50 -0
- package/ts/common/eventUtils.ts +1 -1
- package/ts/common/port80-adapter.ts +1 -1
- package/ts/core/events/index.ts +3 -0
- package/ts/core/index.ts +8 -0
- package/ts/core/models/common-types.ts +91 -0
- package/ts/core/models/index.ts +5 -0
- package/ts/core/utils/event-utils.ts +34 -0
- package/ts/core/utils/index.ts +7 -0
- package/ts/core/utils/ip-utils.ts +175 -0
- package/ts/core/utils/validation-utils.ts +177 -0
- package/ts/{smartproxy/forwarding → forwarding/config}/domain-config.ts +1 -1
- package/ts/{smartproxy/forwarding → forwarding/config}/domain-manager.ts +8 -8
- package/ts/{smartproxy/types/forwarding.types.ts → forwarding/config/forwarding-types.ts} +6 -6
- package/ts/forwarding/config/index.ts +7 -0
- package/ts/{smartproxy/forwarding/forwarding.factory.ts → forwarding/factory/forwarding-factory.ts} +12 -11
- package/ts/forwarding/factory/index.ts +5 -0
- package/ts/{smartproxy/forwarding/forwarding.handler.ts → forwarding/handlers/base-handler.ts} +2 -2
- package/ts/{smartproxy/forwarding/http.handler.ts → forwarding/handlers/http-handler.ts} +13 -4
- package/ts/{smartproxy/forwarding/https-passthrough.handler.ts → forwarding/handlers/https-passthrough-handler.ts} +13 -4
- package/ts/{smartproxy/forwarding/https-terminate-to-http.handler.ts → forwarding/handlers/https-terminate-to-http-handler.ts} +3 -3
- package/ts/{smartproxy/forwarding/https-terminate-to-https.handler.ts → forwarding/handlers/https-terminate-to-https-handler.ts} +3 -3
- package/ts/forwarding/handlers/index.ts +9 -0
- package/ts/forwarding/index.ts +34 -0
- package/ts/http/index.ts +23 -0
- package/ts/http/models/http-types.ts +105 -0
- package/ts/http/port80/acme-interfaces.ts +85 -0
- package/ts/http/port80/challenge-responder.ts +246 -0
- package/ts/http/port80/index.ts +13 -0
- package/ts/{port80handler/classes.port80handler.ts → http/port80/port80-handler.ts} +164 -161
- package/ts/http/redirects/index.ts +3 -0
- package/ts/http/router/index.ts +5 -0
- package/ts/{classes.router.ts → http/router/proxy-router.ts} +27 -20
- package/ts/index.ts +32 -9
- package/ts/plugins.ts +2 -1
- package/ts/proxies/index.ts +8 -0
- package/ts/{networkproxy/classes.np.certificatemanager.ts → proxies/network-proxy/certificate-manager.ts} +17 -16
- package/ts/{networkproxy/classes.np.connectionpool.ts → proxies/network-proxy/connection-pool.ts} +3 -3
- package/ts/proxies/network-proxy/index.ts +13 -0
- package/ts/proxies/network-proxy/models/index.ts +4 -0
- package/ts/{networkproxy/classes.np.types.ts → proxies/network-proxy/models/types.ts} +7 -11
- package/ts/{networkproxy/classes.np.networkproxy.ts → proxies/network-proxy/network-proxy.ts} +31 -24
- package/ts/{networkproxy/classes.np.requesthandler.ts → proxies/network-proxy/request-handler.ts} +12 -7
- package/ts/{networkproxy/classes.np.websockethandler.ts → proxies/network-proxy/websocket-handler.ts} +6 -6
- package/ts/proxies/nftables-proxy/index.ts +5 -0
- package/ts/proxies/nftables-proxy/models/errors.ts +30 -0
- package/ts/proxies/nftables-proxy/models/index.ts +5 -0
- package/ts/proxies/nftables-proxy/models/interfaces.ts +94 -0
- package/ts/{nfttablesproxy/classes.nftablesproxy.ts → proxies/nftables-proxy/nftables-proxy.ts} +24 -126
- package/ts/{smartproxy/classes.pp.connectionhandler.ts → proxies/smart-proxy/connection-handler.ts} +12 -12
- package/ts/{smartproxy/classes.pp.connectionmanager.ts → proxies/smart-proxy/connection-manager.ts} +8 -8
- package/ts/{smartproxy/classes.pp.domainconfigmanager.ts → proxies/smart-proxy/domain-config-manager.ts} +15 -14
- package/ts/proxies/smart-proxy/index.ts +18 -0
- package/ts/proxies/smart-proxy/models/index.ts +4 -0
- package/ts/{smartproxy/classes.pp.interfaces.ts → proxies/smart-proxy/models/interfaces.ts} +12 -8
- package/ts/{smartproxy/classes.pp.networkproxybridge.ts → proxies/smart-proxy/network-proxy-bridge.ts} +14 -14
- package/ts/{smartproxy/classes.pp.portrangemanager.ts → proxies/smart-proxy/port-range-manager.ts} +1 -1
- package/ts/{smartproxy/classes.pp.securitymanager.ts → proxies/smart-proxy/security-manager.ts} +3 -3
- package/ts/{smartproxy/classes.smartproxy.ts → proxies/smart-proxy/smart-proxy.ts} +29 -24
- package/ts/{smartproxy/classes.pp.timeoutmanager.ts → proxies/smart-proxy/timeout-manager.ts} +3 -3
- package/ts/{smartproxy/classes.pp.tlsmanager.ts → proxies/smart-proxy/tls-manager.ts} +3 -3
- package/ts/tls/alerts/index.ts +3 -0
- package/ts/{smartproxy/classes.pp.tlsalert.ts → tls/alerts/tls-alert.ts} +44 -43
- package/ts/tls/index.ts +33 -0
- package/ts/tls/sni/client-hello-parser.ts +629 -0
- package/ts/tls/sni/index.ts +3 -0
- package/ts/tls/sni/sni-extraction.ts +353 -0
- package/ts/tls/sni/sni-handler.ts +264 -0
- package/ts/tls/utils/index.ts +3 -0
- package/ts/tls/utils/tls-utils.ts +201 -0
- package/ts/common/acmeFactory.ts +0 -23
- package/ts/helpers.certificates.ts +0 -30
- package/ts/networkproxy/index.ts +0 -7
- package/ts/smartproxy/classes.pp.certprovisioner.ts +0 -200
- package/ts/smartproxy/classes.pp.snihandler.ts +0 -1281
- package/ts/smartproxy/forwarding/index.ts +0 -52
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import { createLogger } from './models/types.js';
|
|
3
|
+
import { ConnectionPool } from './connection-pool.js';
|
|
4
|
+
import { ProxyRouter } from '../../http/router/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* Handles HTTP request processing and proxying
|
|
7
|
+
*/
|
|
8
|
+
export class RequestHandler {
|
|
9
|
+
constructor(options, connectionPool, router) {
|
|
10
|
+
this.options = options;
|
|
11
|
+
this.connectionPool = connectionPool;
|
|
12
|
+
this.router = router;
|
|
13
|
+
this.defaultHeaders = {};
|
|
14
|
+
this.metricsTracker = null;
|
|
15
|
+
// HTTP/2 client sessions for backend proxying
|
|
16
|
+
this.h2Sessions = new Map();
|
|
17
|
+
this.logger = createLogger(options.logLevel || 'info');
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Set the metrics tracker instance
|
|
21
|
+
*/
|
|
22
|
+
setMetricsTracker(tracker) {
|
|
23
|
+
this.metricsTracker = tracker;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Set default headers to be included in all responses
|
|
27
|
+
*/
|
|
28
|
+
setDefaultHeaders(headers) {
|
|
29
|
+
this.defaultHeaders = {
|
|
30
|
+
...this.defaultHeaders,
|
|
31
|
+
...headers
|
|
32
|
+
};
|
|
33
|
+
this.logger.info('Updated default response headers');
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Get all default headers
|
|
37
|
+
*/
|
|
38
|
+
getDefaultHeaders() {
|
|
39
|
+
return { ...this.defaultHeaders };
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Apply CORS headers to response if configured
|
|
43
|
+
*/
|
|
44
|
+
applyCorsHeaders(res, req) {
|
|
45
|
+
if (!this.options.cors) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
// Apply CORS headers
|
|
49
|
+
if (this.options.cors.allowOrigin) {
|
|
50
|
+
res.setHeader('Access-Control-Allow-Origin', this.options.cors.allowOrigin);
|
|
51
|
+
}
|
|
52
|
+
if (this.options.cors.allowMethods) {
|
|
53
|
+
res.setHeader('Access-Control-Allow-Methods', this.options.cors.allowMethods);
|
|
54
|
+
}
|
|
55
|
+
if (this.options.cors.allowHeaders) {
|
|
56
|
+
res.setHeader('Access-Control-Allow-Headers', this.options.cors.allowHeaders);
|
|
57
|
+
}
|
|
58
|
+
if (this.options.cors.maxAge) {
|
|
59
|
+
res.setHeader('Access-Control-Max-Age', this.options.cors.maxAge.toString());
|
|
60
|
+
}
|
|
61
|
+
// Handle CORS preflight requests
|
|
62
|
+
if (req.method === 'OPTIONS') {
|
|
63
|
+
res.statusCode = 204; // No content
|
|
64
|
+
res.end();
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Apply default headers to response
|
|
70
|
+
*/
|
|
71
|
+
applyDefaultHeaders(res) {
|
|
72
|
+
// Apply default headers
|
|
73
|
+
for (const [key, value] of Object.entries(this.defaultHeaders)) {
|
|
74
|
+
if (!res.hasHeader(key)) {
|
|
75
|
+
res.setHeader(key, value);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Add server identifier if not already set
|
|
79
|
+
if (!res.hasHeader('Server')) {
|
|
80
|
+
res.setHeader('Server', 'NetworkProxy');
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Handle an HTTP request
|
|
85
|
+
*/
|
|
86
|
+
async handleRequest(req, res) {
|
|
87
|
+
// Record start time for logging
|
|
88
|
+
const startTime = Date.now();
|
|
89
|
+
// Apply CORS headers if configured
|
|
90
|
+
this.applyCorsHeaders(res, req);
|
|
91
|
+
// If this is an OPTIONS request, the response has already been ended in applyCorsHeaders
|
|
92
|
+
// so we should return early to avoid trying to set more headers
|
|
93
|
+
if (req.method === 'OPTIONS') {
|
|
94
|
+
// Increment metrics for OPTIONS requests too
|
|
95
|
+
if (this.metricsTracker) {
|
|
96
|
+
this.metricsTracker.incrementRequestsServed();
|
|
97
|
+
}
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
// Apply default headers
|
|
101
|
+
this.applyDefaultHeaders(res);
|
|
102
|
+
// Determine routing configuration
|
|
103
|
+
let proxyConfig;
|
|
104
|
+
try {
|
|
105
|
+
proxyConfig = this.router.routeReq(req);
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
this.logger.error('Error routing request', err);
|
|
109
|
+
res.statusCode = 500;
|
|
110
|
+
res.end('Internal Server Error');
|
|
111
|
+
if (this.metricsTracker)
|
|
112
|
+
this.metricsTracker.incrementFailedRequests();
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (!proxyConfig) {
|
|
116
|
+
this.logger.warn(`No proxy configuration for host: ${req.headers.host}`);
|
|
117
|
+
res.statusCode = 404;
|
|
118
|
+
res.end('Not Found: No proxy configuration for this host');
|
|
119
|
+
if (this.metricsTracker)
|
|
120
|
+
this.metricsTracker.incrementFailedRequests();
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
// Determine protocol to backend (per-domain override or global)
|
|
124
|
+
const backendProto = proxyConfig.backendProtocol || this.options.backendProtocol;
|
|
125
|
+
if (backendProto === 'http2') {
|
|
126
|
+
const destination = this.connectionPool.getNextTarget(proxyConfig.destinationIps, proxyConfig.destinationPorts[0]);
|
|
127
|
+
const key = `${destination.host}:${destination.port}`;
|
|
128
|
+
let session = this.h2Sessions.get(key);
|
|
129
|
+
if (!session || session.closed || session.destroyed) {
|
|
130
|
+
session = plugins.http2.connect(`http://${destination.host}:${destination.port}`);
|
|
131
|
+
this.h2Sessions.set(key, session);
|
|
132
|
+
session.on('error', () => this.h2Sessions.delete(key));
|
|
133
|
+
session.on('close', () => this.h2Sessions.delete(key));
|
|
134
|
+
}
|
|
135
|
+
// Build headers for HTTP/2 request
|
|
136
|
+
const hdrs = {
|
|
137
|
+
':method': req.method,
|
|
138
|
+
':path': req.url,
|
|
139
|
+
':authority': `${destination.host}:${destination.port}`
|
|
140
|
+
};
|
|
141
|
+
for (const [hk, hv] of Object.entries(req.headers)) {
|
|
142
|
+
if (typeof hv === 'string')
|
|
143
|
+
hdrs[hk] = hv;
|
|
144
|
+
}
|
|
145
|
+
const h2Stream = session.request(hdrs);
|
|
146
|
+
req.pipe(h2Stream);
|
|
147
|
+
h2Stream.on('response', (hdrs2) => {
|
|
148
|
+
const status = hdrs2[':status'] || 502;
|
|
149
|
+
res.statusCode = status;
|
|
150
|
+
// Copy headers from HTTP/2 response to HTTP/1 response
|
|
151
|
+
for (const [hk, hv] of Object.entries(hdrs2)) {
|
|
152
|
+
if (!hk.startsWith(':') && hv != null) {
|
|
153
|
+
res.setHeader(hk, hv);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
h2Stream.pipe(res);
|
|
157
|
+
});
|
|
158
|
+
h2Stream.on('error', (err) => {
|
|
159
|
+
res.statusCode = 502;
|
|
160
|
+
res.end(`Bad Gateway: ${err.message}`);
|
|
161
|
+
if (this.metricsTracker)
|
|
162
|
+
this.metricsTracker.incrementFailedRequests();
|
|
163
|
+
});
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
try {
|
|
167
|
+
// Find target based on hostname
|
|
168
|
+
const proxyConfig = this.router.routeReq(req);
|
|
169
|
+
if (!proxyConfig) {
|
|
170
|
+
// No matching proxy configuration
|
|
171
|
+
this.logger.warn(`No proxy configuration for host: ${req.headers.host}`);
|
|
172
|
+
res.statusCode = 404;
|
|
173
|
+
res.end('Not Found: No proxy configuration for this host');
|
|
174
|
+
// Increment failed requests counter
|
|
175
|
+
if (this.metricsTracker) {
|
|
176
|
+
this.metricsTracker.incrementFailedRequests();
|
|
177
|
+
}
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
// Get destination IP using round-robin if multiple IPs configured
|
|
181
|
+
const destination = this.connectionPool.getNextTarget(proxyConfig.destinationIps, proxyConfig.destinationPorts[0]);
|
|
182
|
+
// Create options for the proxy request
|
|
183
|
+
const options = {
|
|
184
|
+
hostname: destination.host,
|
|
185
|
+
port: destination.port,
|
|
186
|
+
path: req.url,
|
|
187
|
+
method: req.method,
|
|
188
|
+
headers: { ...req.headers }
|
|
189
|
+
};
|
|
190
|
+
// Remove host header to avoid issues with virtual hosts on target server
|
|
191
|
+
// The host header should match the target server's expected hostname
|
|
192
|
+
if (options.headers && options.headers.host) {
|
|
193
|
+
if (proxyConfig.rewriteHostHeader) {
|
|
194
|
+
options.headers.host = `${destination.host}:${destination.port}`;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
this.logger.debug(`Proxying request to ${destination.host}:${destination.port}${req.url}`, { method: req.method });
|
|
198
|
+
// Create proxy request
|
|
199
|
+
const proxyReq = plugins.http.request(options, (proxyRes) => {
|
|
200
|
+
// Copy status code
|
|
201
|
+
res.statusCode = proxyRes.statusCode || 500;
|
|
202
|
+
// Copy headers from proxy response to client response
|
|
203
|
+
for (const [key, value] of Object.entries(proxyRes.headers)) {
|
|
204
|
+
if (value !== undefined) {
|
|
205
|
+
res.setHeader(key, value);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// Pipe proxy response to client response
|
|
209
|
+
proxyRes.pipe(res);
|
|
210
|
+
// Increment served requests counter when the response finishes
|
|
211
|
+
res.on('finish', () => {
|
|
212
|
+
if (this.metricsTracker) {
|
|
213
|
+
this.metricsTracker.incrementRequestsServed();
|
|
214
|
+
}
|
|
215
|
+
// Log the completed request
|
|
216
|
+
const duration = Date.now() - startTime;
|
|
217
|
+
this.logger.debug(`Request completed in ${duration}ms: ${req.method} ${req.url} ${res.statusCode}`, { duration, statusCode: res.statusCode });
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
// Handle proxy request errors
|
|
221
|
+
proxyReq.on('error', (error) => {
|
|
222
|
+
const duration = Date.now() - startTime;
|
|
223
|
+
this.logger.error(`Proxy error for ${req.method} ${req.url}: ${error.message}`, { duration, error: error.message });
|
|
224
|
+
// Increment failed requests counter
|
|
225
|
+
if (this.metricsTracker) {
|
|
226
|
+
this.metricsTracker.incrementFailedRequests();
|
|
227
|
+
}
|
|
228
|
+
// Check if headers have already been sent
|
|
229
|
+
if (!res.headersSent) {
|
|
230
|
+
res.statusCode = 502;
|
|
231
|
+
res.end(`Bad Gateway: ${error.message}`);
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
// If headers already sent, just close the connection
|
|
235
|
+
res.end();
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
// Pipe request body to proxy request and handle client-side errors
|
|
239
|
+
req.pipe(proxyReq);
|
|
240
|
+
// Handle client disconnection
|
|
241
|
+
req.on('error', (error) => {
|
|
242
|
+
this.logger.debug(`Client connection error: ${error.message}`);
|
|
243
|
+
proxyReq.destroy();
|
|
244
|
+
// Increment failed requests counter on client errors
|
|
245
|
+
if (this.metricsTracker) {
|
|
246
|
+
this.metricsTracker.incrementFailedRequests();
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
// Handle response errors
|
|
250
|
+
res.on('error', (error) => {
|
|
251
|
+
this.logger.debug(`Response error: ${error.message}`);
|
|
252
|
+
proxyReq.destroy();
|
|
253
|
+
// Increment failed requests counter on response errors
|
|
254
|
+
if (this.metricsTracker) {
|
|
255
|
+
this.metricsTracker.incrementFailedRequests();
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
// Handle any unexpected errors
|
|
261
|
+
this.logger.error(`Unexpected error handling request: ${error.message}`, { error: error.stack });
|
|
262
|
+
// Increment failed requests counter
|
|
263
|
+
if (this.metricsTracker) {
|
|
264
|
+
this.metricsTracker.incrementFailedRequests();
|
|
265
|
+
}
|
|
266
|
+
if (!res.headersSent) {
|
|
267
|
+
res.statusCode = 500;
|
|
268
|
+
res.end('Internal Server Error');
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
res.end();
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Handle HTTP/2 stream requests by proxying to HTTP/1 backends
|
|
277
|
+
*/
|
|
278
|
+
async handleHttp2(stream, headers) {
|
|
279
|
+
const startTime = Date.now();
|
|
280
|
+
const method = headers[':method'] || 'GET';
|
|
281
|
+
const path = headers[':path'] || '/';
|
|
282
|
+
// If configured to proxy to backends over HTTP/2, use HTTP/2 client sessions
|
|
283
|
+
if (this.options.backendProtocol === 'http2') {
|
|
284
|
+
const authority = headers[':authority'] || '';
|
|
285
|
+
const host = authority.split(':')[0];
|
|
286
|
+
const fakeReq = { headers: { host }, method: headers[':method'], url: headers[':path'], socket: stream.session.socket };
|
|
287
|
+
const proxyConfig = this.router.routeReq(fakeReq);
|
|
288
|
+
if (!proxyConfig) {
|
|
289
|
+
stream.respond({ ':status': 404 });
|
|
290
|
+
stream.end('Not Found');
|
|
291
|
+
if (this.metricsTracker)
|
|
292
|
+
this.metricsTracker.incrementFailedRequests();
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
const destination = this.connectionPool.getNextTarget(proxyConfig.destinationIps, proxyConfig.destinationPorts[0]);
|
|
296
|
+
const key = `${destination.host}:${destination.port}`;
|
|
297
|
+
let session = this.h2Sessions.get(key);
|
|
298
|
+
if (!session || session.closed || session.destroyed) {
|
|
299
|
+
session = plugins.http2.connect(`http://${destination.host}:${destination.port}`);
|
|
300
|
+
this.h2Sessions.set(key, session);
|
|
301
|
+
session.on('error', () => this.h2Sessions.delete(key));
|
|
302
|
+
session.on('close', () => this.h2Sessions.delete(key));
|
|
303
|
+
}
|
|
304
|
+
// Build headers for backend HTTP/2 request
|
|
305
|
+
const h2Headers = {
|
|
306
|
+
':method': headers[':method'],
|
|
307
|
+
':path': headers[':path'],
|
|
308
|
+
':authority': `${destination.host}:${destination.port}`
|
|
309
|
+
};
|
|
310
|
+
for (const [k, v] of Object.entries(headers)) {
|
|
311
|
+
if (!k.startsWith(':') && typeof v === 'string') {
|
|
312
|
+
h2Headers[k] = v;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
const h2Stream2 = session.request(h2Headers);
|
|
316
|
+
stream.pipe(h2Stream2);
|
|
317
|
+
h2Stream2.on('response', (hdrs) => {
|
|
318
|
+
// Map status and headers to client
|
|
319
|
+
const resp = { ':status': hdrs[':status'] };
|
|
320
|
+
for (const [hk, hv] of Object.entries(hdrs)) {
|
|
321
|
+
if (!hk.startsWith(':') && hv)
|
|
322
|
+
resp[hk] = hv;
|
|
323
|
+
}
|
|
324
|
+
stream.respond(resp);
|
|
325
|
+
h2Stream2.pipe(stream);
|
|
326
|
+
});
|
|
327
|
+
h2Stream2.on('error', (err) => {
|
|
328
|
+
stream.respond({ ':status': 502 });
|
|
329
|
+
stream.end(`Bad Gateway: ${err.message}`);
|
|
330
|
+
if (this.metricsTracker)
|
|
331
|
+
this.metricsTracker.incrementFailedRequests();
|
|
332
|
+
});
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
try {
|
|
336
|
+
// Determine host for routing
|
|
337
|
+
const authority = headers[':authority'] || '';
|
|
338
|
+
const host = authority.split(':')[0];
|
|
339
|
+
// Fake request object for routing
|
|
340
|
+
const fakeReq = { headers: { host }, method, url: path, socket: stream.session.socket };
|
|
341
|
+
const proxyConfig = this.router.routeReq(fakeReq);
|
|
342
|
+
if (!proxyConfig) {
|
|
343
|
+
stream.respond({ ':status': 404 });
|
|
344
|
+
stream.end('Not Found');
|
|
345
|
+
if (this.metricsTracker)
|
|
346
|
+
this.metricsTracker.incrementFailedRequests();
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
// Select backend target
|
|
350
|
+
const destination = this.connectionPool.getNextTarget(proxyConfig.destinationIps, proxyConfig.destinationPorts[0]);
|
|
351
|
+
// Build headers for HTTP/1 proxy
|
|
352
|
+
const outboundHeaders = {};
|
|
353
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
354
|
+
if (typeof key === 'string' && typeof value === 'string' && !key.startsWith(':')) {
|
|
355
|
+
outboundHeaders[key] = value;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
if (outboundHeaders.host && proxyConfig.rewriteHostHeader) {
|
|
359
|
+
outboundHeaders.host = `${destination.host}:${destination.port}`;
|
|
360
|
+
}
|
|
361
|
+
// Create HTTP/1 proxy request
|
|
362
|
+
const proxyReq = plugins.http.request({ hostname: destination.host, port: destination.port, path, method, headers: outboundHeaders }, (proxyRes) => {
|
|
363
|
+
// Map status and headers back to HTTP/2
|
|
364
|
+
const responseHeaders = {};
|
|
365
|
+
for (const [k, v] of Object.entries(proxyRes.headers)) {
|
|
366
|
+
if (v !== undefined) {
|
|
367
|
+
responseHeaders[k] = v;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
stream.respond({ ':status': proxyRes.statusCode || 500, ...responseHeaders });
|
|
371
|
+
proxyRes.pipe(stream);
|
|
372
|
+
stream.on('close', () => proxyReq.destroy());
|
|
373
|
+
stream.on('error', () => proxyReq.destroy());
|
|
374
|
+
if (this.metricsTracker)
|
|
375
|
+
stream.on('end', () => this.metricsTracker.incrementRequestsServed());
|
|
376
|
+
});
|
|
377
|
+
proxyReq.on('error', (err) => {
|
|
378
|
+
stream.respond({ ':status': 502 });
|
|
379
|
+
stream.end(`Bad Gateway: ${err.message}`);
|
|
380
|
+
if (this.metricsTracker)
|
|
381
|
+
this.metricsTracker.incrementFailedRequests();
|
|
382
|
+
});
|
|
383
|
+
// Pipe client stream to backend
|
|
384
|
+
stream.pipe(proxyReq);
|
|
385
|
+
}
|
|
386
|
+
catch (err) {
|
|
387
|
+
stream.respond({ ':status': 500 });
|
|
388
|
+
stream.end('Internal Server Error');
|
|
389
|
+
if (this.metricsTracker)
|
|
390
|
+
this.metricsTracker.incrementFailedRequests();
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxdWVzdC1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvcHJveGllcy9uZXR3b3JrLXByb3h5L3JlcXVlc3QtaGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGtCQUFrQixDQUFDO0FBQzVDLE9BQU8sRUFBMkMsWUFBWSxFQUE0QixNQUFNLG1CQUFtQixDQUFDO0FBQ3BILE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUN0RCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFhekQ7O0dBRUc7QUFDSCxNQUFNLE9BQU8sY0FBYztJQU96QixZQUNVLE9BQTZCLEVBQzdCLGNBQThCLEVBQzlCLE1BQW1CO1FBRm5CLFlBQU8sR0FBUCxPQUFPLENBQXNCO1FBQzdCLG1CQUFjLEdBQWQsY0FBYyxDQUFnQjtRQUM5QixXQUFNLEdBQU4sTUFBTSxDQUFhO1FBVHJCLG1CQUFjLEdBQThCLEVBQUUsQ0FBQztRQUUvQyxtQkFBYyxHQUEyQixJQUFJLENBQUM7UUFDdEQsOENBQThDO1FBQ3RDLGVBQVUsR0FBa0QsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQU81RSxJQUFJLENBQUMsTUFBTSxHQUFHLFlBQVksQ0FBQyxPQUFPLENBQUMsUUFBUSxJQUFJLE1BQU0sQ0FBQyxDQUFDO0lBQ3pELENBQUM7SUFFRDs7T0FFRztJQUNJLGlCQUFpQixDQUFDLE9BQXdCO1FBQy9DLElBQUksQ0FBQyxjQUFjLEdBQUcsT0FBTyxDQUFDO0lBQ2hDLENBQUM7SUFFRDs7T0FFRztJQUNJLGlCQUFpQixDQUFDLE9BQWtDO1FBQ3pELElBQUksQ0FBQyxjQUFjLEdBQUc7WUFDcEIsR0FBRyxJQUFJLENBQUMsY0FBYztZQUN0QixHQUFHLE9BQU87U0FDWCxDQUFDO1FBQ0YsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsa0NBQWtDLENBQUMsQ0FB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
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import { type INetworkProxyOptions } from './models/types.js';
|
|
3
|
+
import { ConnectionPool } from './connection-pool.js';
|
|
4
|
+
import { ProxyRouter } from '../../http/router/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* Handles WebSocket connections and proxying
|
|
7
|
+
*/
|
|
8
|
+
export declare class WebSocketHandler {
|
|
9
|
+
private options;
|
|
10
|
+
private connectionPool;
|
|
11
|
+
private router;
|
|
12
|
+
private heartbeatInterval;
|
|
13
|
+
private wsServer;
|
|
14
|
+
private logger;
|
|
15
|
+
constructor(options: INetworkProxyOptions, connectionPool: ConnectionPool, router: ProxyRouter);
|
|
16
|
+
/**
|
|
17
|
+
* Initialize WebSocket server on an existing HTTPS server
|
|
18
|
+
*/
|
|
19
|
+
initialize(server: plugins.https.Server): void;
|
|
20
|
+
/**
|
|
21
|
+
* Start the heartbeat interval to check for inactive WebSocket connections
|
|
22
|
+
*/
|
|
23
|
+
private startHeartbeat;
|
|
24
|
+
/**
|
|
25
|
+
* Handle a new WebSocket connection
|
|
26
|
+
*/
|
|
27
|
+
private handleWebSocketConnection;
|
|
28
|
+
/**
|
|
29
|
+
* Get information about active WebSocket connections
|
|
30
|
+
*/
|
|
31
|
+
getConnectionInfo(): {
|
|
32
|
+
activeConnections: number;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Shutdown the WebSocket handler
|
|
36
|
+
*/
|
|
37
|
+
shutdown(): void;
|
|
38
|
+
}
|