@push.rocks/smartproxy 25.17.10 → 26.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/changelog.md +15 -0
- package/dist_rust/rustproxy_linux_amd64 +0 -0
- package/dist_rust/rustproxy_linux_arm64 +0 -0
- package/dist_ts/00_commitinfo_data.js +2 -2
- package/dist_ts/core/index.d.ts +0 -1
- package/dist_ts/core/index.js +1 -2
- package/dist_ts/core/models/index.d.ts +0 -1
- package/dist_ts/core/models/index.js +1 -2
- package/dist_ts/core/utils/index.d.ts +0 -12
- package/dist_ts/core/utils/index.js +1 -13
- package/dist_ts/index.d.ts +0 -3
- package/dist_ts/index.js +2 -7
- package/dist_ts/protocols/http/index.d.ts +0 -1
- package/dist_ts/protocols/http/index.js +1 -2
- package/dist_ts/protocols/index.d.ts +0 -7
- package/dist_ts/protocols/index.js +1 -8
- package/dist_ts/proxies/smart-proxy/models/metrics-types.d.ts +20 -0
- package/dist_ts/proxies/smart-proxy/rust-metrics-adapter.d.ts +2 -1
- package/dist_ts/proxies/smart-proxy/rust-metrics-adapter.js +4 -1
- package/dist_ts/proxies/smart-proxy/socket-handler-server.js +6 -1
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.d.ts +0 -7
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.js +50 -51
- package/dist_ts/routing/index.d.ts +0 -1
- package/dist_ts/routing/index.js +1 -3
- package/package.json +1 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/core/index.ts +0 -1
- package/ts/core/models/index.ts +0 -1
- package/ts/core/utils/index.ts +0 -12
- package/ts/index.ts +1 -7
- package/ts/protocols/http/index.ts +1 -2
- package/ts/protocols/index.ts +0 -7
- package/ts/proxies/smart-proxy/models/metrics-types.ts +21 -0
- package/ts/proxies/smart-proxy/rust-metrics-adapter.ts +4 -1
- package/ts/proxies/smart-proxy/socket-handler-server.ts +6 -0
- package/ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.ts +60 -59
- package/ts/routing/index.ts +0 -3
- package/dist_ts/core/events/index.d.ts +0 -4
- package/dist_ts/core/events/index.js +0 -5
- package/dist_ts/core/models/socket-augmentation.d.ts +0 -15
- package/dist_ts/core/models/socket-augmentation.js +0 -18
- package/dist_ts/core/utils/async-utils.d.ts +0 -81
- package/dist_ts/core/utils/async-utils.js +0 -216
- package/dist_ts/core/utils/binary-heap.d.ts +0 -73
- package/dist_ts/core/utils/binary-heap.js +0 -193
- package/dist_ts/core/utils/enhanced-connection-pool.d.ts +0 -110
- package/dist_ts/core/utils/enhanced-connection-pool.js +0 -325
- package/dist_ts/core/utils/fs-utils.d.ts +0 -144
- package/dist_ts/core/utils/fs-utils.js +0 -252
- package/dist_ts/core/utils/ip-utils.d.ts +0 -69
- package/dist_ts/core/utils/ip-utils.js +0 -270
- package/dist_ts/core/utils/lifecycle-component.d.ts +0 -59
- package/dist_ts/core/utils/lifecycle-component.js +0 -211
- package/dist_ts/core/utils/log-deduplicator.d.ts +0 -39
- package/dist_ts/core/utils/log-deduplicator.js +0 -305
- package/dist_ts/core/utils/security-utils.d.ts +0 -111
- package/dist_ts/core/utils/security-utils.js +0 -212
- package/dist_ts/core/utils/shared-security-manager.d.ts +0 -128
- package/dist_ts/core/utils/shared-security-manager.js +0 -362
- package/dist_ts/core/utils/socket-utils.d.ts +0 -63
- package/dist_ts/core/utils/socket-utils.js +0 -249
- package/dist_ts/core/utils/template-utils.d.ts +0 -37
- package/dist_ts/core/utils/template-utils.js +0 -104
- package/dist_ts/core/utils/validation-utils.d.ts +0 -61
- package/dist_ts/core/utils/validation-utils.js +0 -149
- package/dist_ts/core/utils/websocket-utils.d.ts +0 -22
- package/dist_ts/core/utils/websocket-utils.js +0 -30
- package/dist_ts/detection/detectors/http-detector.d.ts +0 -33
- package/dist_ts/detection/detectors/http-detector.js +0 -101
- package/dist_ts/detection/detectors/quick-detector.d.ts +0 -28
- package/dist_ts/detection/detectors/quick-detector.js +0 -131
- package/dist_ts/detection/detectors/routing-extractor.d.ts +0 -28
- package/dist_ts/detection/detectors/routing-extractor.js +0 -122
- package/dist_ts/detection/detectors/tls-detector.d.ts +0 -47
- package/dist_ts/detection/detectors/tls-detector.js +0 -183
- package/dist_ts/detection/index.d.ts +0 -17
- package/dist_ts/detection/index.js +0 -22
- package/dist_ts/detection/models/detection-types.d.ts +0 -87
- package/dist_ts/detection/models/detection-types.js +0 -5
- package/dist_ts/detection/models/interfaces.d.ts +0 -97
- package/dist_ts/detection/models/interfaces.js +0 -5
- package/dist_ts/detection/protocol-detector.d.ts +0 -79
- package/dist_ts/detection/protocol-detector.js +0 -253
- package/dist_ts/detection/utils/buffer-utils.d.ts +0 -61
- package/dist_ts/detection/utils/buffer-utils.js +0 -127
- package/dist_ts/detection/utils/fragment-manager.d.ts +0 -31
- package/dist_ts/detection/utils/fragment-manager.js +0 -53
- package/dist_ts/detection/utils/parser-utils.d.ts +0 -42
- package/dist_ts/detection/utils/parser-utils.js +0 -63
- package/dist_ts/protocols/common/fragment-handler.d.ts +0 -73
- package/dist_ts/protocols/common/fragment-handler.js +0 -121
- package/dist_ts/protocols/common/index.d.ts +0 -7
- package/dist_ts/protocols/common/index.js +0 -8
- package/dist_ts/protocols/common/types.d.ts +0 -68
- package/dist_ts/protocols/common/types.js +0 -7
- package/dist_ts/protocols/http/parser.d.ts +0 -58
- package/dist_ts/protocols/http/parser.js +0 -184
- package/dist_ts/protocols/proxy/index.d.ts +0 -5
- package/dist_ts/protocols/proxy/index.js +0 -6
- package/dist_ts/protocols/proxy/types.d.ts +0 -47
- package/dist_ts/protocols/proxy/types.js +0 -6
- package/dist_ts/protocols/tls/alerts/index.d.ts +0 -4
- package/dist_ts/protocols/tls/alerts/index.js +0 -5
- package/dist_ts/protocols/tls/alerts/tls-alert.d.ts +0 -150
- package/dist_ts/protocols/tls/alerts/tls-alert.js +0 -226
- package/dist_ts/protocols/tls/index.d.ts +0 -12
- package/dist_ts/protocols/tls/index.js +0 -27
- package/dist_ts/protocols/tls/sni/client-hello-parser.d.ts +0 -100
- package/dist_ts/protocols/tls/sni/client-hello-parser.js +0 -463
- package/dist_ts/protocols/tls/sni/index.d.ts +0 -5
- package/dist_ts/protocols/tls/sni/index.js +0 -6
- package/dist_ts/protocols/tls/sni/sni-extraction.d.ts +0 -58
- package/dist_ts/protocols/tls/sni/sni-extraction.js +0 -275
- package/dist_ts/protocols/tls/utils/index.d.ts +0 -4
- package/dist_ts/protocols/tls/utils/index.js +0 -5
- package/dist_ts/protocols/tls/utils/tls-utils.d.ts +0 -158
- package/dist_ts/protocols/tls/utils/tls-utils.js +0 -187
- package/dist_ts/protocols/websocket/constants.d.ts +0 -55
- package/dist_ts/protocols/websocket/constants.js +0 -58
- package/dist_ts/protocols/websocket/index.d.ts +0 -7
- package/dist_ts/protocols/websocket/index.js +0 -8
- package/dist_ts/protocols/websocket/types.d.ts +0 -47
- package/dist_ts/protocols/websocket/types.js +0 -5
- package/dist_ts/protocols/websocket/utils.d.ts +0 -25
- package/dist_ts/protocols/websocket/utils.js +0 -103
- package/dist_ts/routing/router/http-router.d.ts +0 -89
- package/dist_ts/routing/router/http-router.js +0 -205
- package/dist_ts/routing/router/index.d.ts +0 -5
- package/dist_ts/routing/router/index.js +0 -6
- package/dist_ts/tls/index.d.ts +0 -16
- package/dist_ts/tls/index.js +0 -24
- package/dist_ts/tls/sni/index.d.ts +0 -4
- package/dist_ts/tls/sni/index.js +0 -5
- package/dist_ts/tls/sni/sni-handler.d.ts +0 -154
- package/dist_ts/tls/sni/sni-handler.js +0 -191
- package/ts/core/events/index.ts +0 -3
- package/ts/core/models/socket-augmentation.ts +0 -38
- package/ts/core/utils/async-utils.ts +0 -275
- package/ts/core/utils/binary-heap.ts +0 -225
- package/ts/core/utils/enhanced-connection-pool.ts +0 -425
- package/ts/core/utils/fs-utils.ts +0 -270
- package/ts/core/utils/ip-utils.ts +0 -303
- package/ts/core/utils/lifecycle-component.ts +0 -251
- package/ts/core/utils/log-deduplicator.ts +0 -370
- package/ts/core/utils/security-utils.ts +0 -305
- package/ts/core/utils/shared-security-manager.ts +0 -470
- package/ts/core/utils/socket-utils.ts +0 -322
- package/ts/core/utils/template-utils.ts +0 -124
- package/ts/core/utils/validation-utils.ts +0 -177
- package/ts/core/utils/websocket-utils.ts +0 -33
- package/ts/detection/detectors/http-detector.ts +0 -127
- package/ts/detection/detectors/quick-detector.ts +0 -148
- package/ts/detection/detectors/routing-extractor.ts +0 -147
- package/ts/detection/detectors/tls-detector.ts +0 -223
- package/ts/detection/index.ts +0 -25
- package/ts/detection/models/detection-types.ts +0 -102
- package/ts/detection/models/interfaces.ts +0 -115
- package/ts/detection/protocol-detector.ts +0 -319
- package/ts/detection/utils/buffer-utils.ts +0 -141
- package/ts/detection/utils/fragment-manager.ts +0 -64
- package/ts/detection/utils/parser-utils.ts +0 -77
- package/ts/protocols/common/fragment-handler.ts +0 -167
- package/ts/protocols/common/index.ts +0 -8
- package/ts/protocols/common/types.ts +0 -76
- package/ts/protocols/http/parser.ts +0 -219
- package/ts/protocols/proxy/index.ts +0 -6
- package/ts/protocols/proxy/types.ts +0 -53
- package/ts/protocols/tls/alerts/index.ts +0 -3
- package/ts/protocols/tls/alerts/tls-alert.ts +0 -259
- package/ts/protocols/tls/index.ts +0 -37
- package/ts/protocols/tls/sni/client-hello-parser.ts +0 -629
- package/ts/protocols/tls/sni/index.ts +0 -6
- package/ts/protocols/tls/sni/sni-extraction.ts +0 -353
- package/ts/protocols/tls/utils/index.ts +0 -3
- package/ts/protocols/tls/utils/tls-utils.ts +0 -201
- package/ts/protocols/websocket/constants.ts +0 -60
- package/ts/protocols/websocket/index.ts +0 -8
- package/ts/protocols/websocket/types.ts +0 -53
- package/ts/protocols/websocket/utils.ts +0 -98
- package/ts/routing/router/http-router.ts +0 -266
- package/ts/routing/router/index.ts +0 -7
- package/ts/tls/index.ts +0 -29
- package/ts/tls/sni/index.ts +0 -3
- package/ts/tls/sni/sni-handler.ts +0 -264
|
@@ -5,8 +5,43 @@
|
|
|
5
5
|
* like echoing, proxying, HTTP responses, and redirects.
|
|
6
6
|
*/
|
|
7
7
|
import * as plugins from '../../../../plugins.js';
|
|
8
|
-
import { ProtocolDetector } from '../../../../detection/index.js';
|
|
9
8
|
import { createSocketTracker } from '../../../../core/utils/socket-tracker.js';
|
|
9
|
+
/**
|
|
10
|
+
* Minimal HTTP request parser for socket handlers.
|
|
11
|
+
* Parses method, path, and optionally headers from a raw buffer.
|
|
12
|
+
*/
|
|
13
|
+
function parseHttpRequest(data, extractHeaders = false) {
|
|
14
|
+
const str = data.toString('utf8');
|
|
15
|
+
const headerEnd = str.indexOf('\r\n\r\n');
|
|
16
|
+
const isComplete = headerEnd !== -1;
|
|
17
|
+
const headerSection = isComplete ? str.slice(0, headerEnd) : str;
|
|
18
|
+
const lines = headerSection.split('\r\n');
|
|
19
|
+
const requestLine = lines[0];
|
|
20
|
+
if (!requestLine)
|
|
21
|
+
return null;
|
|
22
|
+
const parts = requestLine.split(' ');
|
|
23
|
+
if (parts.length < 2)
|
|
24
|
+
return null;
|
|
25
|
+
const method = parts[0];
|
|
26
|
+
const path = parts[1];
|
|
27
|
+
// Quick check: valid HTTP method
|
|
28
|
+
const validMethods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS', 'CONNECT', 'TRACE'];
|
|
29
|
+
if (!validMethods.includes(method))
|
|
30
|
+
return null;
|
|
31
|
+
const headers = {};
|
|
32
|
+
if (extractHeaders) {
|
|
33
|
+
for (let i = 1; i < lines.length; i++) {
|
|
34
|
+
const colonIdx = lines[i].indexOf(':');
|
|
35
|
+
if (colonIdx > 0) {
|
|
36
|
+
const name = lines[i].slice(0, colonIdx).trim().toLowerCase();
|
|
37
|
+
const value = lines[i].slice(colonIdx + 1).trim();
|
|
38
|
+
headers[name] = value;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const body = isComplete ? str.slice(headerEnd + 4) : undefined;
|
|
43
|
+
return { method, path, headers, isComplete, body };
|
|
44
|
+
}
|
|
10
45
|
/**
|
|
11
46
|
* Pre-built socket handlers for common use cases
|
|
12
47
|
*/
|
|
@@ -92,23 +127,16 @@ export const SocketHandlers = {
|
|
|
92
127
|
},
|
|
93
128
|
/**
|
|
94
129
|
* HTTP redirect handler
|
|
95
|
-
* Uses the centralized detection module for HTTP parsing
|
|
96
130
|
*/
|
|
97
131
|
httpRedirect: (locationTemplate, statusCode = 301) => (socket, context) => {
|
|
98
132
|
const tracker = createSocketTracker(socket);
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
// Use detection module for parsing
|
|
104
|
-
const detectionResult = await ProtocolDetector.detectWithConnectionTracking(data, connectionId, { extractFullHeaders: false } // We only need method and path
|
|
105
|
-
);
|
|
106
|
-
if (detectionResult.protocol === 'http' && detectionResult.connectionInfo.path) {
|
|
107
|
-
const method = detectionResult.connectionInfo.method || 'GET';
|
|
108
|
-
const path = detectionResult.connectionInfo.path || '/';
|
|
133
|
+
const handleData = (data) => {
|
|
134
|
+
const parsed = parseHttpRequest(data);
|
|
135
|
+
if (parsed) {
|
|
136
|
+
const path = parsed.path || '/';
|
|
109
137
|
const domain = context.domain || 'localhost';
|
|
110
138
|
const port = context.port;
|
|
111
|
-
|
|
139
|
+
const finalLocation = locationTemplate
|
|
112
140
|
.replace('{domain}', domain)
|
|
113
141
|
.replace('{port}', String(port))
|
|
114
142
|
.replace('{path}', path)
|
|
@@ -126,16 +154,11 @@ export const SocketHandlers = {
|
|
|
126
154
|
socket.write(response);
|
|
127
155
|
}
|
|
128
156
|
else {
|
|
129
|
-
// Not a valid HTTP request, close connection
|
|
130
157
|
socket.write('HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n');
|
|
131
158
|
}
|
|
132
159
|
socket.end();
|
|
133
|
-
// Clean up detection state
|
|
134
|
-
ProtocolDetector.cleanupConnections();
|
|
135
|
-
// Clean up all tracked resources
|
|
136
160
|
tracker.cleanup();
|
|
137
161
|
};
|
|
138
|
-
// Use tracker to manage the listener
|
|
139
162
|
socket.once('data', handleData);
|
|
140
163
|
tracker.addListener('error', (err) => {
|
|
141
164
|
tracker.safeDestroy(err);
|
|
@@ -146,36 +169,26 @@ export const SocketHandlers = {
|
|
|
146
169
|
},
|
|
147
170
|
/**
|
|
148
171
|
* HTTP server handler for ACME challenges and other HTTP needs
|
|
149
|
-
* Uses the centralized detection module for HTTP parsing
|
|
150
172
|
*/
|
|
151
173
|
httpServer: (handler) => (socket, context) => {
|
|
152
174
|
const tracker = createSocketTracker(socket);
|
|
153
175
|
let requestParsed = false;
|
|
154
176
|
let responseTimer = null;
|
|
155
|
-
const
|
|
156
|
-
socketId: context.connectionId || `${Date.now()}-${Math.random()}`
|
|
157
|
-
});
|
|
158
|
-
const processData = async (data) => {
|
|
177
|
+
const processData = (data) => {
|
|
159
178
|
if (requestParsed)
|
|
160
|
-
return; // Only handle the first request
|
|
161
|
-
// Use HttpDetector for parsing
|
|
162
|
-
const detectionResult = await ProtocolDetector.detectWithConnectionTracking(data, connectionId, { extractFullHeaders: true });
|
|
163
|
-
if (detectionResult.protocol !== 'http' || !detectionResult.isComplete) {
|
|
164
|
-
// Not a complete HTTP request yet
|
|
165
179
|
return;
|
|
180
|
+
const parsed = parseHttpRequest(data, true);
|
|
181
|
+
if (!parsed || !parsed.isComplete) {
|
|
182
|
+
return; // Not a complete HTTP request yet
|
|
166
183
|
}
|
|
167
184
|
requestParsed = true;
|
|
168
|
-
// Remove data listener after parsing request
|
|
169
185
|
socket.removeListener('data', processData);
|
|
170
|
-
const connInfo = detectionResult.connectionInfo;
|
|
171
|
-
// Create request object from detection result
|
|
172
186
|
const req = {
|
|
173
|
-
method:
|
|
174
|
-
url:
|
|
175
|
-
headers:
|
|
176
|
-
body:
|
|
187
|
+
method: parsed.method,
|
|
188
|
+
url: parsed.path,
|
|
189
|
+
headers: parsed.headers,
|
|
190
|
+
body: parsed.body || ''
|
|
177
191
|
};
|
|
178
|
-
// Create response object
|
|
179
192
|
let statusCode = 200;
|
|
180
193
|
const responseHeaders = {};
|
|
181
194
|
let ended = false;
|
|
@@ -190,7 +203,6 @@ export const SocketHandlers = {
|
|
|
190
203
|
if (ended)
|
|
191
204
|
return;
|
|
192
205
|
ended = true;
|
|
193
|
-
// Clear response timer since we're sending now
|
|
194
206
|
if (responseTimer) {
|
|
195
207
|
clearTimeout(responseTimer);
|
|
196
208
|
responseTimer = null;
|
|
@@ -222,14 +234,12 @@ export const SocketHandlers = {
|
|
|
222
234
|
};
|
|
223
235
|
try {
|
|
224
236
|
handler(req, res);
|
|
225
|
-
// Ensure response is sent even if handler doesn't call send()
|
|
226
237
|
responseTimer = setTimeout(() => {
|
|
227
238
|
if (!ended) {
|
|
228
239
|
res.send('');
|
|
229
240
|
}
|
|
230
241
|
responseTimer = null;
|
|
231
242
|
}, 1000);
|
|
232
|
-
// Track and unref the timer
|
|
233
243
|
tracker.addTimer(responseTimer);
|
|
234
244
|
}
|
|
235
245
|
catch (error) {
|
|
@@ -237,11 +247,9 @@ export const SocketHandlers = {
|
|
|
237
247
|
res.status(500);
|
|
238
248
|
res.send('Internal Server Error');
|
|
239
249
|
}
|
|
240
|
-
// Use safeDestroy for error cases
|
|
241
250
|
tracker.safeDestroy(error instanceof Error ? error : new Error('Handler error'));
|
|
242
251
|
}
|
|
243
252
|
};
|
|
244
|
-
// Use tracker to manage listeners
|
|
245
253
|
tracker.addListener('data', processData);
|
|
246
254
|
tracker.addListener('error', (err) => {
|
|
247
255
|
if (!requestParsed) {
|
|
@@ -249,25 +257,16 @@ export const SocketHandlers = {
|
|
|
249
257
|
}
|
|
250
258
|
});
|
|
251
259
|
tracker.addListener('close', () => {
|
|
252
|
-
// Clear any pending response timer
|
|
253
260
|
if (responseTimer) {
|
|
254
261
|
clearTimeout(responseTimer);
|
|
255
262
|
responseTimer = null;
|
|
256
263
|
}
|
|
257
|
-
// Clean up detection state
|
|
258
|
-
ProtocolDetector.cleanupConnections();
|
|
259
|
-
// Clean up all tracked resources
|
|
260
264
|
tracker.cleanup();
|
|
261
265
|
});
|
|
262
266
|
}
|
|
263
267
|
};
|
|
264
268
|
/**
|
|
265
269
|
* Create a socket handler route configuration
|
|
266
|
-
* @param domains Domain(s) to match
|
|
267
|
-
* @param ports Port(s) to listen on
|
|
268
|
-
* @param handler Socket handler function
|
|
269
|
-
* @param options Additional route options
|
|
270
|
-
* @returns Route configuration object
|
|
271
270
|
*/
|
|
272
271
|
export function createSocketHandlerRoute(domains, ports, handler, options = {}) {
|
|
273
272
|
return {
|
|
@@ -284,4 +283,4 @@ export function createSocketHandlerRoute(domains, ports, handler, options = {})
|
|
|
284
283
|
}
|
|
285
284
|
};
|
|
286
285
|
}
|
|
287
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29ja2V0LWhhbmRsZXJzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vdHMvcHJveGllcy9zbWFydC1wcm94eS91dGlscy9yb3V0ZS1oZWxwZXJzL3NvY2tldC1oYW5kbGVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7R0FLRztBQUVILE9BQU8sS0FBSyxPQUFPLE1BQU0sd0JBQXdCLENBQUM7QUFFbEQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDbEUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sMENBQTBDLENBQUM7QUFFL0U7O0dBRUc7QUFDSCxNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUc7SUFDNUI7O09BRUc7SUFDSCxJQUFJLEVBQUUsQ0FBQyxNQUEwQixFQUFFLE9BQXNCLEVBQUUsRUFBRTtRQUMzRCxNQUFNLENBQUMsS0FBSyxDQUFDLHFCQUFxQixDQUFDLENBQUM7UUFDcEMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDaEQsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxFQUFFLENBQUMsVUFBa0IsRUFBRSxVQUFrQixFQUFFLEVBQUUsQ0FBQyxDQUFDLE1BQTBCLEVBQUUsT0FBc0IsRUFBRSxFQUFFO1FBQ3hHLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUMzRCxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3BCLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDcEIsTUFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFD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
|
|
286
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29ja2V0LWhhbmRsZXJzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vdHMvcHJveGllcy9zbWFydC1wcm94eS91dGlscy9yb3V0ZS1oZWxwZXJzL3NvY2tldC1oYW5kbGVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7R0FLRztBQUVILE9BQU8sS0FBSyxPQUFPLE1BQU0sd0JBQXdCLENBQUM7QUFFbEQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sMENBQTBDLENBQUM7QUFFL0U7OztHQUdHO0FBQ0gsU0FBUyxnQkFBZ0IsQ0FBQyxJQUFZLEVBQUUsaUJBQTBCLEtBQUs7SUFPckUsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNsQyxNQUFNLFNBQVMsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzFDLE1BQU0sVUFBVSxHQUFHLFNBQVMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUNwQyxNQUFNLGFBQWEsR0FBRyxVQUFVLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7SUFDakUsTUFBTSxLQUFLLEdBQUcsYUFBYSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMxQyxNQUFNLFdBQVcsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDN0IsSUFBSSxDQUFDLFdBQVc7UUFBRSxPQUFPLElBQUksQ0FBQztJQUU5QixNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3JDLElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFFbEMsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hCLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUV0QixpQ0FBaUM7SUFDakMsTUFBTSxZQUFZLEdBQUcsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3RHLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBRWhELE1BQU0sT0FBTyxHQUEyQixFQUFFLENBQUM7SUFDM0MsSUFBSSxjQUFjLEVBQUUsQ0FBQztRQUNuQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ3RDLE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDdkMsSUFBSSxRQUFRLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQ2pCLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUM5RCxNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFFBQVEsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFDbEQsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQztZQUN4QixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFRCxNQUFNLElBQUksR0FBRyxVQUFVLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7SUFFL0QsT0FBTyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsQ0FBQztBQUNyRCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUc7SUFDNUI7O09BRUc7SUFDSCxJQUFJLEVBQUUsQ0FBQyxNQUEwQixFQUFFLE9BQXNCLEVBQUUsRUFBRTtRQUMzRCxNQUFNLENBQUMsS0FBSyxDQUFDLHFCQUFxQixDQUFDLENBQUM7UUFDcEMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDaEQsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxFQUFFLENBQUMsVUFBa0IsRUFBRSxVQUFrQixFQUFFLEVBQUUsQ0FBQyxDQUFDLE1BQTBCLEVBQUUsT0FBc0IsRUFBRSxFQUFFO1FBQ3hHLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUMzRCxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3BCLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDcEIsTUFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDM0MsTUFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDM0MsTUFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxHQUFHLEVBQUUsRUFBRTtZQUN6QixPQUFPLENBQUMsS0FBSyxDQUFDLHFCQUFxQixFQUFFLEdBQUcsQ0FBQyxDQUFDO1lBQzFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNuQixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNILFlBQVksRUFBRSxDQUFDLE9BQTJELEVBQUUsRUFBRSxDQUFDLENBQUMsTUFBMEIsRUFBRSxPQUFzQixFQUFFLEVBQUU7UUFDcEksSUFBSSxNQUFNLEdBQUcsRUFBRSxDQUFDO1FBQ2hCLE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUMsSUFBSSxFQUFFLEVBQUU7WUFDekIsTUFBTSxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUMxQixNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2pDLE1BQU0sR0FBRyxLQUFLLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxDQUFDO1lBQzNCLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUU7Z0JBQ25CLElBQUksSUFBSSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUM7b0JBQ2hCLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUM7Z0JBQy9CLENBQUM7WUFDSCxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOztPQUVHO0lBQ0gsWUFBWSxFQUFFLENBQUMsVUFBa0IsRUFBRSxJQUFZLEVBQUUsRUFBRSxDQUFDLENBQUMsTUFBMEIsRUFBRSxPQUFzQixFQUFFLEVBQUU7UUFDekcsTUFBTSxRQUFRLEdBQUc7WUFDZixZQUFZLFVBQVUsSUFBSSxVQUFVLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRTtZQUMvRCwwQkFBMEI7WUFDMUIsbUJBQW1CLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDaEMsbUJBQW1CO1lBQ25CLEVBQUU7WUFDRixJQUFJO1NBQ0wsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFZixNQUFNLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3ZCLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUNmLENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssRUFBRSxDQUFDLE9BQWdCLEVBQUUsRUFBRSxDQUFDLENBQUMsTUFBMEIsRUFBRSxPQUFzQixFQUFFLEVBQUU7UUFDbEYsTUFBTSxZQUFZLEdBQUcsT0FBTyxJQUFJLDJCQUEyQixPQUFPLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDOUUsSUFBSSxZQUFZLEVBQUUsQ0FBQztZQUNqQixNQUFNLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQzdCLENBQUM7UUFDRCxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDZixDQUFDO0lBRUQ7O09BRUc7SUFDSCxTQUFTLEVBQUUsQ0FBQyxhQUFxQixHQUFHLEVBQUUsT0FBZ0IsRUFBRSxFQUFFLENBQUMsQ0FBQyxNQUEwQixFQUFFLE9BQXNCLEVBQUUsRUFBRTtRQUNoSCxNQUFNLGNBQWMsR0FBRyx3QkFBd0IsT0FBTyxDQUFDLE1BQU0sSUFBSSxPQUFPLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDcEYsTUFBTSxZQUFZLEdBQUcsT0FBTyxJQUFJLGNBQWMsQ0FBQztRQUUvQyxNQUFNLFFBQVEsR0FBRztZQUNmLFlBQVksVUFBVSxJQUFJLFlBQVksRUFBRTtZQUN4QywwQkFBMEI7WUFDMUIsbUJBQW1CLFlBQVksQ0FBQyxNQUFNLEVBQUU7WUFDeEMsbUJBQW1CO1lBQ25CLEVBQUU7WUFDRixZQUFZO1NBQ2IsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFZixNQUFNLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3ZCLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUNmLENBQUM7SUFFRDs7T0FFRztJQUNILFlBQVksRUFBRSxDQUFDLGdCQUF3QixFQUFFLGFBQXFCLEdBQUcsRUFBRSxFQUFFLENBQUMsQ0FBQyxNQUEwQixFQUFFLE9BQXNCLEVBQUUsRUFBRTtRQUMzSCxNQUFNLE9BQU8sR0FBRyxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUU1QyxNQUFNLFVBQVUsR0FBRyxDQUFDLElBQVksRUFBRSxFQUFFO1lBQ2xDLE1BQU0sTUFBTSxHQUFHLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDO1lBRXRDLElBQUksTUFBTSxFQUFFLENBQUM7Z0JBQ1gsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksSUFBSSxHQUFHLENBQUM7Z0JBQ2hDLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLElBQUksV0FBVyxDQUFDO2dCQUM3QyxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDO2dCQUUxQixNQUFNLGFBQWEsR0FBRyxnQkFBZ0I7cUJBQ25DLE9BQU8sQ0FBQyxVQUFVLEVBQUUsTUFBTSxDQUFDO3FCQUMzQixPQUFPLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztxQkFDL0IsT0FBTyxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUM7cUJBQ3ZCLE9BQU8sQ0FBQyxZQUFZLEVBQUUsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUUzQyxNQUFNLE9BQU8sR0FBRyxrQkFBa0IsYUFBYSxFQUFFLENBQUM7Z0JBQ2xELE1BQU0sUUFBUSxHQUFHO29CQUNmLFlBQVksVUFBVSxJQUFJLFVBQVUsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDLG1CQUFtQixDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUU7b0JBQzlFLGFBQWEsYUFBYSxFQUFFO29CQUM1QiwwQkFBMEI7b0JBQzFCLG1CQUFtQixPQUFPLENBQUMsTUFBTSxFQUFFO29CQUNuQyxtQkFBbUI7b0JBQ25CLEVBQUU7b0JBQ0YsT0FBTztpQkFDUixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFFZixNQUFNLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ3pCLENBQUM7aUJBQU0sQ0FBQztnQkFDTixNQUFNLENBQUMsS0FBSyxDQUFDLHVEQUF1RCxDQUFDLENBQUM7WUFDeEUsQ0FBQztZQUVELE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNiLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNwQixDQUFDLENBQUM7UUFFRixNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUMsQ0FBQztRQUVoQyxPQUFPLENBQUMsV0FBVyxDQUFDLE9BQU8sRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFO1lBQ25DLE9BQU8sQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDM0IsQ0FBQyxDQUFDLENBQUM7UUFFSCxPQUFPLENBQUMsV0FBVyxDQUFDLE9BQU8sRUFBRSxHQUFHLEVBQUU7WUFDaEMsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3BCLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOztPQUVHO0lBQ0gsVUFBVSxFQUFFLENBQUMsT0FBOE8sRUFBRSxFQUFFLENBQUMsQ0FBQyxNQUEwQixFQUFFLE9BQXNCLEVBQUUsRUFBRTtRQUNyVCxNQUFNLE9BQU8sR0FBRyxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUM1QyxJQUFJLGFBQWEsR0FBRyxLQUFLLENBQUM7UUFDMUIsSUFBSSxhQUFhLEdBQTBCLElBQUksQ0FBQztRQUVoRCxNQUFNLFdBQVcsR0FBRyxDQUFDLElBQVksRUFBRSxFQUFFO1lBQ25DLElBQUksYUFBYTtnQkFBRSxPQUFPO1lBRTFCLE1BQU0sTUFBTSxHQUFHLGdCQUFnQixDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztZQUU1QyxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDO2dCQUNsQyxPQUFPLENBQUMsa0NBQWtDO1lBQzVDLENBQUM7WUFFRCxhQUFhLEdBQUcsSUFBSSxDQUFDO1lBQ3JCLE1BQU0sQ0FBQyxjQUFjLENBQUMsTUFBTSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1lBRTNDLE1BQU0sR0FBRyxHQUFHO2dCQUNWLE1BQU0sRUFBRSxNQUFNLENBQUMsTUFBTTtnQkFDckIsR0FBRyxFQUFFLE1BQU0sQ0FBQyxJQUFJO2dCQUNoQixPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU87Z0JBQ3ZCLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxJQUFJLEVBQUU7YUFDeEIsQ0FBQztZQUVGLElBQUksVUFBVSxHQUFHLEdBQUcsQ0FBQztZQUNyQixNQUFNLGVBQWUsR0FBMkIsRUFBRSxDQUFDO1lBQ25ELElBQUksS0FBSyxHQUFHLEtBQUssQ0FBQztZQUVsQixNQUFNLEdBQUcsR0FBRztnQkFDVixNQUFNLEVBQUUsQ0FBQyxJQUFZLEVBQUUsRUFBRTtvQkFDdkIsVUFBVSxHQUFHLElBQUksQ0FBQztnQkFDcEIsQ0FBQztnQkFDRCxNQUFNLEVBQUUsQ0FBQyxJQUFZLEVBQUUsS0FBYSxFQUFFLEVBQUU7b0JBQ3RDLGVBQWUsQ0FBQyxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUM7Z0JBQ2hDLENBQUM7Z0JBQ0QsSUFBSSxFQUFFLENBQUMsSUFBWSxFQUFFLEVBQUU7b0JBQ3JCLElBQUksS0FBSzt3QkFBRSxPQUFPO29CQUNsQixLQUFLLEdBQUcsSUFBSSxDQUFDO29CQUViLElBQUksYUFBYSxFQUFFLENBQUM7d0JBQ2xCLFlBQVksQ0FBQyxhQUFhLENBQUMsQ0FBQzt3QkFDNUIsYUFBYSxHQUFHLElBQUksQ0FBQztvQkFDdkIsQ0FBQztvQkFFRCxJQUFJLENBQUMsZUFBZSxDQUFDLGNBQWMsQ0FBQyxFQUFFLENBQUM7d0JBQ3JDLGVBQWUsQ0FBQyxjQUFjLENBQUMsR0FBRyxZQUFZLENBQUM7b0JBQ2pELENBQUM7b0JBQ0QsZUFBZSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztvQkFDeEQsZUFBZSxDQUFDLFlBQVksQ0FBQyxHQUFHLE9BQU8sQ0FBQztvQkFFeEMsTUFBTSxVQUFVLEdBQUcsVUFBVSxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7d0JBQzdCLFVBQVUsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDOzRCQUNsQyxVQUFVLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDO29CQUUzRSxJQUFJLFFBQVEsR0FBRyxZQUFZLFVBQVUsSUFBSSxVQUFVLE1BQU0sQ0FBQztvQkFDMUQsS0FBSyxNQUFNLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLEVBQUUsQ0FBQzt3QkFDNUQsUUFBUSxJQUFJLEdBQUcsSUFBSSxLQUFLLEtBQUssTUFBTSxDQUFDO29CQUN0QyxDQUFDO29CQUNELFFBQVEsSUFBSSxNQUFNLENBQUM7b0JBQ25CLFFBQVEsSUFBSSxJQUFJLENBQUM7b0JBRWpCLE1BQU0sQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7b0JBQ3ZCLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQztnQkFDZixDQUFDO2dCQUNELEdBQUcsRUFBRSxHQUFHLEVBQUU7b0JBQ1IsSUFBSSxLQUFLO3dCQUFFLE9BQU87b0JBQ2xCLEtBQUssR0FBRyxJQUFJLENBQUM7b0JBQ2IsTUFBTSxDQUFDLEtBQUssQ0FBQyxtRUFBbUUsQ0FBQyxDQUFDO29CQUNsRixNQUFNLENBQUMsR0FBRyxFQUFFLENBQUM7Z0JBQ2YsQ0FBQzthQUNGLENBQUM7WUFFRixJQUFJLENBQUM7Z0JBQ0gsT0FBTyxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztnQkFDbEIsYUFBYSxHQUFHLFVBQVUsQ0FBQyxHQUFHLEVBQUU7b0JBQzlCLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQzt3QkFDWCxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO29CQUNmLENBQUM7b0JBQ0QsYUFBYSxHQUFHLElBQUksQ0FBQztnQkFDdkIsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUNULE9BQU8sQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLENBQUM7WUFDbEMsQ0FBQztZQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7Z0JBQ2YsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO29CQUNYLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7b0JBQ2hCLEdBQUcsQ0FBQyxJQUFJLENBQUMsdUJBQXVCLENBQUMsQ0FBQztnQkFDcEMsQ0FBQztnQkFDRCxPQUFPLENBQUMsV0FBVyxDQUFDLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQztZQUNuRixDQUFDO1FBQ0gsQ0FBQyxDQUFDO1FBRUYsT0FBTyxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFFekMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxHQUFHLEVBQUUsRUFBRTtZQUNuQyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7Z0JBQ25CLE9BQU8sQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDM0IsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO1FBRUgsT0FBTyxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFO1lBQ2hDLElBQUksYUFBYSxFQUFFLENBQUM7Z0JBQ2xCLFlBQVksQ0FBQyxhQUFhLENBQUMsQ0FBQztnQkFDNUIsYUFBYSxHQUFHLElBQUksQ0FBQztZQUN2QixDQUFDO1lBQ0QsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3BCLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztDQUNGLENBQUM7QUFFRjs7R0FFRztBQUNILE1BQU0sVUFBVSx3QkFBd0IsQ0FDdEMsT0FBMEIsRUFDMUIsS0FBaUIsRUFDakIsT0FBNkQsRUFDN0QsVUFJSSxFQUFFO0lBRU4sT0FBTztRQUNMLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSSxJQUFJLHNCQUFzQjtRQUM1QyxRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVEsS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUU7UUFDaEUsS0FBSyxFQUFFO1lBQ0wsT0FBTztZQUNQLEtBQUs7WUFDTCxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksSUFBSSxFQUFFLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7U0FDNUM7UUFDRCxNQUFNLEVBQUU7WUFDTixJQUFJLEVBQUUsZ0JBQWdCO1lBQ3RCLGFBQWEsRUFBRSxPQUFPO1NBQ3ZCO0tBQ0YsQ0FBQztBQUNKLENBQUMifQ==
|
package/dist_ts/routing/index.js
CHANGED
|
@@ -3,6 +3,4 @@
|
|
|
3
3
|
*/
|
|
4
4
|
// Export types and models
|
|
5
5
|
export * from './models/http-types.js';
|
|
6
|
-
|
|
7
|
-
export * from './router/index.js';
|
|
8
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9yb3V0aW5nL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsMEJBQTBCO0FBQzFCLGNBQWMsd0JBQXdCLENBQUM7QUFFdkMsOEJBQThCO0FBQzlCLGNBQWMsbUJBQW1CLENBQUMifQ==
|
|
6
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9yb3V0aW5nL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsMEJBQTBCO0FBQzFCLGNBQWMsd0JBQXdCLENBQUMifQ==
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@push.rocks/smartproxy",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "26.1.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A powerful proxy package with unified route-based configuration for high traffic management. Features include SSL/TLS support, flexible routing patterns, WebSocket handling, advanced security options, and automatic ACME certificate management.",
|
|
6
6
|
"main": "dist_ts/index.js",
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@push.rocks/smartproxy',
|
|
6
|
-
version: '
|
|
6
|
+
version: '26.1.0',
|
|
7
7
|
description: 'A powerful proxy package with unified route-based configuration for high traffic management. Features include SSL/TLS support, flexible routing patterns, WebSocket handling, advanced security options, and automatic ACME certificate management.'
|
|
8
8
|
}
|
package/ts/core/index.ts
CHANGED
package/ts/core/models/index.ts
CHANGED
package/ts/core/utils/index.ts
CHANGED
|
@@ -2,16 +2,4 @@
|
|
|
2
2
|
* Core utility functions
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
export * from './validation-utils.js';
|
|
6
|
-
export * from './ip-utils.js';
|
|
7
|
-
export * from './template-utils.js';
|
|
8
|
-
export * from './security-utils.js';
|
|
9
|
-
export * from './shared-security-manager.js';
|
|
10
|
-
export * from './websocket-utils.js';
|
|
11
5
|
export * from './logger.js';
|
|
12
|
-
export * from './async-utils.js';
|
|
13
|
-
export * from './fs-utils.js';
|
|
14
|
-
export * from './lifecycle-component.js';
|
|
15
|
-
export * from './binary-heap.js';
|
|
16
|
-
export * from './enhanced-connection-pool.js';
|
|
17
|
-
export * from './socket-utils.js';
|
package/ts/index.ts
CHANGED
|
@@ -11,18 +11,12 @@ export type { ISmartProxyOptions, IConnectionRecord, IRouteConfig, IRouteMatch,
|
|
|
11
11
|
export type { TSmartProxyCertProvisionObject, ICertProvisionEventComms, ICertificateIssuedEvent, ICertificateFailedEvent } from './proxies/smart-proxy/models/interfaces.js';
|
|
12
12
|
export * from './proxies/smart-proxy/utils/index.js';
|
|
13
13
|
|
|
14
|
-
// Original: export * from './smartproxy/classes.pp.snihandler.js'
|
|
15
|
-
// Now we export from the new module
|
|
16
|
-
export { SniHandler } from './tls/sni/sni-handler.js';
|
|
17
|
-
|
|
18
14
|
// Core types and utilities
|
|
19
15
|
export * from './core/models/common-types.js';
|
|
20
16
|
|
|
21
17
|
// Export IAcmeOptions from one place only
|
|
22
18
|
export type { IAcmeOptions } from './proxies/smart-proxy/models/interfaces.js';
|
|
23
19
|
|
|
24
|
-
// Modular exports
|
|
25
|
-
export * as tls from './tls/index.js';
|
|
20
|
+
// Modular exports
|
|
26
21
|
export * as routing from './routing/index.js';
|
|
27
|
-
export * as detection from './detection/index.js';
|
|
28
22
|
export * as protocols from './protocols/index.js';
|
package/ts/protocols/index.ts
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Protocol-specific modules for smartproxy
|
|
3
|
-
*
|
|
4
|
-
* This directory contains generic protocol knowledge separated from
|
|
5
|
-
* smartproxy-specific implementation details.
|
|
6
3
|
*/
|
|
7
4
|
|
|
8
|
-
export * as common from './common/index.js';
|
|
9
|
-
export * as tls from './tls/index.js';
|
|
10
5
|
export * as http from './http/index.js';
|
|
11
|
-
export * as proxy from './proxy/index.js';
|
|
12
|
-
export * as websocket from './websocket/index.js';
|
|
@@ -72,6 +72,7 @@ export interface IMetrics {
|
|
|
72
72
|
byBackend(): Map<string, IBackendMetrics>;
|
|
73
73
|
protocols(): Map<string, string>;
|
|
74
74
|
topByErrors(limit?: number): Array<{ backend: string; errors: number }>;
|
|
75
|
+
detectedProtocols(): IProtocolCacheEntry[];
|
|
75
76
|
};
|
|
76
77
|
|
|
77
78
|
// UDP metrics
|
|
@@ -113,6 +114,26 @@ export interface IMetricsConfig {
|
|
|
113
114
|
prometheusPrefix: string; // Default: smartproxy_
|
|
114
115
|
}
|
|
115
116
|
|
|
117
|
+
/**
|
|
118
|
+
* Protocol cache entry from the Rust proxy's auto-detection cache.
|
|
119
|
+
* Shows which protocol (h1/h2/h3) is detected for each backend+domain pair,
|
|
120
|
+
* including failure suppression state with escalating cooldowns.
|
|
121
|
+
*/
|
|
122
|
+
export interface IProtocolCacheEntry {
|
|
123
|
+
host: string;
|
|
124
|
+
port: number;
|
|
125
|
+
domain: string | null;
|
|
126
|
+
protocol: string;
|
|
127
|
+
h3Port: number | null;
|
|
128
|
+
ageSecs: number;
|
|
129
|
+
h2Suppressed: boolean;
|
|
130
|
+
h3Suppressed: boolean;
|
|
131
|
+
h2CooldownRemainingSecs: number | null;
|
|
132
|
+
h3CooldownRemainingSecs: number | null;
|
|
133
|
+
h2ConsecutiveFailures: number | null;
|
|
134
|
+
h3ConsecutiveFailures: number | null;
|
|
135
|
+
}
|
|
136
|
+
|
|
116
137
|
/**
|
|
117
138
|
* Per-backend metrics
|
|
118
139
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { IMetrics, IBackendMetrics, IThroughputData, IThroughputHistoryPoint } from './models/metrics-types.js';
|
|
1
|
+
import type { IMetrics, IBackendMetrics, IProtocolCacheEntry, IThroughputData, IThroughputHistoryPoint } from './models/metrics-types.js';
|
|
2
2
|
import type { RustProxyBridge } from './rust-proxy-bridge.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -216,6 +216,9 @@ export class RustMetricsAdapter implements IMetrics {
|
|
|
216
216
|
result.sort((a, b) => b.errors - a.errors);
|
|
217
217
|
return result.slice(0, limit);
|
|
218
218
|
},
|
|
219
|
+
detectedProtocols: (): IProtocolCacheEntry[] => {
|
|
220
|
+
return this.cache?.detectedProtocols ?? [];
|
|
221
|
+
},
|
|
219
222
|
};
|
|
220
223
|
|
|
221
224
|
public udp = {
|
|
@@ -274,6 +274,12 @@ export class SocketHandlerServer {
|
|
|
274
274
|
backend.pipe(socket);
|
|
275
275
|
});
|
|
276
276
|
|
|
277
|
+
// Track backend socket for cleanup on stop()
|
|
278
|
+
this.activeSockets.add(backend);
|
|
279
|
+
backend.on('close', () => {
|
|
280
|
+
this.activeSockets.delete(backend);
|
|
281
|
+
});
|
|
282
|
+
|
|
277
283
|
// Connect timeout: if backend doesn't connect within 30s, destroy both
|
|
278
284
|
backend.setTimeout(30_000);
|
|
279
285
|
|
|
@@ -7,9 +7,54 @@
|
|
|
7
7
|
|
|
8
8
|
import * as plugins from '../../../../plugins.js';
|
|
9
9
|
import type { IRouteConfig, TPortRange, IRouteContext } from '../../models/route-types.js';
|
|
10
|
-
import { ProtocolDetector } from '../../../../detection/index.js';
|
|
11
10
|
import { createSocketTracker } from '../../../../core/utils/socket-tracker.js';
|
|
12
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Minimal HTTP request parser for socket handlers.
|
|
14
|
+
* Parses method, path, and optionally headers from a raw buffer.
|
|
15
|
+
*/
|
|
16
|
+
function parseHttpRequest(data: Buffer, extractHeaders: boolean = false): {
|
|
17
|
+
method: string;
|
|
18
|
+
path: string;
|
|
19
|
+
headers: Record<string, string>;
|
|
20
|
+
isComplete: boolean;
|
|
21
|
+
body?: string;
|
|
22
|
+
} | null {
|
|
23
|
+
const str = data.toString('utf8');
|
|
24
|
+
const headerEnd = str.indexOf('\r\n\r\n');
|
|
25
|
+
const isComplete = headerEnd !== -1;
|
|
26
|
+
const headerSection = isComplete ? str.slice(0, headerEnd) : str;
|
|
27
|
+
const lines = headerSection.split('\r\n');
|
|
28
|
+
const requestLine = lines[0];
|
|
29
|
+
if (!requestLine) return null;
|
|
30
|
+
|
|
31
|
+
const parts = requestLine.split(' ');
|
|
32
|
+
if (parts.length < 2) return null;
|
|
33
|
+
|
|
34
|
+
const method = parts[0];
|
|
35
|
+
const path = parts[1];
|
|
36
|
+
|
|
37
|
+
// Quick check: valid HTTP method
|
|
38
|
+
const validMethods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS', 'CONNECT', 'TRACE'];
|
|
39
|
+
if (!validMethods.includes(method)) return null;
|
|
40
|
+
|
|
41
|
+
const headers: Record<string, string> = {};
|
|
42
|
+
if (extractHeaders) {
|
|
43
|
+
for (let i = 1; i < lines.length; i++) {
|
|
44
|
+
const colonIdx = lines[i].indexOf(':');
|
|
45
|
+
if (colonIdx > 0) {
|
|
46
|
+
const name = lines[i].slice(0, colonIdx).trim().toLowerCase();
|
|
47
|
+
const value = lines[i].slice(colonIdx + 1).trim();
|
|
48
|
+
headers[name] = value;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const body = isComplete ? str.slice(headerEnd + 4) : undefined;
|
|
54
|
+
|
|
55
|
+
return { method, path, headers, isComplete, body };
|
|
56
|
+
}
|
|
57
|
+
|
|
13
58
|
/**
|
|
14
59
|
* Pre-built socket handlers for common use cases
|
|
15
60
|
*/
|
|
@@ -104,30 +149,19 @@ export const SocketHandlers = {
|
|
|
104
149
|
|
|
105
150
|
/**
|
|
106
151
|
* HTTP redirect handler
|
|
107
|
-
* Uses the centralized detection module for HTTP parsing
|
|
108
152
|
*/
|
|
109
153
|
httpRedirect: (locationTemplate: string, statusCode: number = 301) => (socket: plugins.net.Socket, context: IRouteContext) => {
|
|
110
154
|
const tracker = createSocketTracker(socket);
|
|
111
|
-
const connectionId = ProtocolDetector.createConnectionId({
|
|
112
|
-
socketId: context.connectionId || `${Date.now()}-${Math.random()}`
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
const handleData = async (data: Buffer) => {
|
|
116
|
-
// Use detection module for parsing
|
|
117
|
-
const detectionResult = await ProtocolDetector.detectWithConnectionTracking(
|
|
118
|
-
data,
|
|
119
|
-
connectionId,
|
|
120
|
-
{ extractFullHeaders: false } // We only need method and path
|
|
121
|
-
);
|
|
122
155
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const path = detectionResult.connectionInfo.path || '/';
|
|
156
|
+
const handleData = (data: Buffer) => {
|
|
157
|
+
const parsed = parseHttpRequest(data);
|
|
126
158
|
|
|
159
|
+
if (parsed) {
|
|
160
|
+
const path = parsed.path || '/';
|
|
127
161
|
const domain = context.domain || 'localhost';
|
|
128
162
|
const port = context.port;
|
|
129
163
|
|
|
130
|
-
|
|
164
|
+
const finalLocation = locationTemplate
|
|
131
165
|
.replace('{domain}', domain)
|
|
132
166
|
.replace('{port}', String(port))
|
|
133
167
|
.replace('{path}', path)
|
|
@@ -146,18 +180,13 @@ export const SocketHandlers = {
|
|
|
146
180
|
|
|
147
181
|
socket.write(response);
|
|
148
182
|
} else {
|
|
149
|
-
// Not a valid HTTP request, close connection
|
|
150
183
|
socket.write('HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n');
|
|
151
184
|
}
|
|
152
185
|
|
|
153
186
|
socket.end();
|
|
154
|
-
// Clean up detection state
|
|
155
|
-
ProtocolDetector.cleanupConnections();
|
|
156
|
-
// Clean up all tracked resources
|
|
157
187
|
tracker.cleanup();
|
|
158
188
|
};
|
|
159
189
|
|
|
160
|
-
// Use tracker to manage the listener
|
|
161
190
|
socket.once('data', handleData);
|
|
162
191
|
|
|
163
192
|
tracker.addListener('error', (err) => {
|
|
@@ -171,45 +200,31 @@ export const SocketHandlers = {
|
|
|
171
200
|
|
|
172
201
|
/**
|
|
173
202
|
* HTTP server handler for ACME challenges and other HTTP needs
|
|
174
|
-
* Uses the centralized detection module for HTTP parsing
|
|
175
203
|
*/
|
|
176
204
|
httpServer: (handler: (req: { method: string; url: string; headers: Record<string, string>; body?: string }, res: { status: (code: number) => void; header: (name: string, value: string) => void; send: (data: string) => void; end: () => void }) => void) => (socket: plugins.net.Socket, context: IRouteContext) => {
|
|
177
205
|
const tracker = createSocketTracker(socket);
|
|
178
206
|
let requestParsed = false;
|
|
179
207
|
let responseTimer: NodeJS.Timeout | null = null;
|
|
180
|
-
const connectionId = ProtocolDetector.createConnectionId({
|
|
181
|
-
socketId: context.connectionId || `${Date.now()}-${Math.random()}`
|
|
182
|
-
});
|
|
183
208
|
|
|
184
|
-
const processData =
|
|
185
|
-
if (requestParsed) return;
|
|
209
|
+
const processData = (data: Buffer) => {
|
|
210
|
+
if (requestParsed) return;
|
|
186
211
|
|
|
187
|
-
|
|
188
|
-
const detectionResult = await ProtocolDetector.detectWithConnectionTracking(
|
|
189
|
-
data,
|
|
190
|
-
connectionId,
|
|
191
|
-
{ extractFullHeaders: true }
|
|
192
|
-
);
|
|
212
|
+
const parsed = parseHttpRequest(data, true);
|
|
193
213
|
|
|
194
|
-
if (
|
|
195
|
-
// Not a complete HTTP request yet
|
|
196
|
-
return;
|
|
214
|
+
if (!parsed || !parsed.isComplete) {
|
|
215
|
+
return; // Not a complete HTTP request yet
|
|
197
216
|
}
|
|
198
217
|
|
|
199
218
|
requestParsed = true;
|
|
200
|
-
// Remove data listener after parsing request
|
|
201
219
|
socket.removeListener('data', processData);
|
|
202
|
-
const connInfo = detectionResult.connectionInfo;
|
|
203
220
|
|
|
204
|
-
// Create request object from detection result
|
|
205
221
|
const req = {
|
|
206
|
-
method:
|
|
207
|
-
url:
|
|
208
|
-
headers:
|
|
209
|
-
body:
|
|
222
|
+
method: parsed.method,
|
|
223
|
+
url: parsed.path,
|
|
224
|
+
headers: parsed.headers,
|
|
225
|
+
body: parsed.body || ''
|
|
210
226
|
};
|
|
211
227
|
|
|
212
|
-
// Create response object
|
|
213
228
|
let statusCode = 200;
|
|
214
229
|
const responseHeaders: Record<string, string> = {};
|
|
215
230
|
let ended = false;
|
|
@@ -225,7 +240,6 @@ export const SocketHandlers = {
|
|
|
225
240
|
if (ended) return;
|
|
226
241
|
ended = true;
|
|
227
242
|
|
|
228
|
-
// Clear response timer since we're sending now
|
|
229
243
|
if (responseTimer) {
|
|
230
244
|
clearTimeout(responseTimer);
|
|
231
245
|
responseTimer = null;
|
|
@@ -261,26 +275,22 @@ export const SocketHandlers = {
|
|
|
261
275
|
|
|
262
276
|
try {
|
|
263
277
|
handler(req, res);
|
|
264
|
-
// Ensure response is sent even if handler doesn't call send()
|
|
265
278
|
responseTimer = setTimeout(() => {
|
|
266
279
|
if (!ended) {
|
|
267
280
|
res.send('');
|
|
268
281
|
}
|
|
269
282
|
responseTimer = null;
|
|
270
283
|
}, 1000);
|
|
271
|
-
// Track and unref the timer
|
|
272
284
|
tracker.addTimer(responseTimer);
|
|
273
285
|
} catch (error) {
|
|
274
286
|
if (!ended) {
|
|
275
287
|
res.status(500);
|
|
276
288
|
res.send('Internal Server Error');
|
|
277
289
|
}
|
|
278
|
-
// Use safeDestroy for error cases
|
|
279
290
|
tracker.safeDestroy(error instanceof Error ? error : new Error('Handler error'));
|
|
280
291
|
}
|
|
281
292
|
};
|
|
282
293
|
|
|
283
|
-
// Use tracker to manage listeners
|
|
284
294
|
tracker.addListener('data', processData);
|
|
285
295
|
|
|
286
296
|
tracker.addListener('error', (err) => {
|
|
@@ -290,14 +300,10 @@ export const SocketHandlers = {
|
|
|
290
300
|
});
|
|
291
301
|
|
|
292
302
|
tracker.addListener('close', () => {
|
|
293
|
-
// Clear any pending response timer
|
|
294
303
|
if (responseTimer) {
|
|
295
304
|
clearTimeout(responseTimer);
|
|
296
305
|
responseTimer = null;
|
|
297
306
|
}
|
|
298
|
-
// Clean up detection state
|
|
299
|
-
ProtocolDetector.cleanupConnections();
|
|
300
|
-
// Clean up all tracked resources
|
|
301
307
|
tracker.cleanup();
|
|
302
308
|
});
|
|
303
309
|
}
|
|
@@ -305,11 +311,6 @@ export const SocketHandlers = {
|
|
|
305
311
|
|
|
306
312
|
/**
|
|
307
313
|
* Create a socket handler route configuration
|
|
308
|
-
* @param domains Domain(s) to match
|
|
309
|
-
* @param ports Port(s) to listen on
|
|
310
|
-
* @param handler Socket handler function
|
|
311
|
-
* @param options Additional route options
|
|
312
|
-
* @returns Route configuration object
|
|
313
314
|
*/
|
|
314
315
|
export function createSocketHandlerRoute(
|
|
315
316
|
domains: string | string[],
|