@push.rocks/smartproxy 21.1.7 → 22.6.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.
Files changed (155) hide show
  1. package/changelog.md +109 -0
  2. package/dist_rust/rustproxy +0 -0
  3. package/dist_ts/00_commitinfo_data.js +1 -1
  4. package/dist_ts/core/utils/shared-security-manager.d.ts +17 -0
  5. package/dist_ts/core/utils/shared-security-manager.js +66 -1
  6. package/dist_ts/index.d.ts +1 -5
  7. package/dist_ts/index.js +3 -9
  8. package/dist_ts/protocols/common/fragment-handler.js +5 -1
  9. package/dist_ts/proxies/http-proxy/default-certificates.d.ts +54 -0
  10. package/dist_ts/proxies/http-proxy/default-certificates.js +127 -0
  11. package/dist_ts/proxies/http-proxy/http-proxy.d.ts +1 -1
  12. package/dist_ts/proxies/http-proxy/http-proxy.js +9 -14
  13. package/dist_ts/proxies/http-proxy/index.d.ts +5 -1
  14. package/dist_ts/proxies/http-proxy/index.js +6 -2
  15. package/dist_ts/proxies/http-proxy/security-manager.d.ts +4 -12
  16. package/dist_ts/proxies/http-proxy/security-manager.js +66 -99
  17. package/dist_ts/proxies/index.d.ts +1 -5
  18. package/dist_ts/proxies/index.js +2 -6
  19. package/dist_ts/proxies/nftables-proxy/index.d.ts +1 -0
  20. package/dist_ts/proxies/nftables-proxy/index.js +2 -1
  21. package/dist_ts/proxies/nftables-proxy/nftables-proxy.d.ts +4 -26
  22. package/dist_ts/proxies/nftables-proxy/nftables-proxy.js +84 -236
  23. package/dist_ts/proxies/nftables-proxy/utils/index.d.ts +9 -0
  24. package/dist_ts/proxies/nftables-proxy/utils/index.js +12 -0
  25. package/dist_ts/proxies/nftables-proxy/utils/nft-command-executor.d.ts +66 -0
  26. package/dist_ts/proxies/nftables-proxy/utils/nft-command-executor.js +131 -0
  27. package/dist_ts/proxies/nftables-proxy/utils/nft-port-spec-normalizer.d.ts +39 -0
  28. package/dist_ts/proxies/nftables-proxy/utils/nft-port-spec-normalizer.js +112 -0
  29. package/dist_ts/proxies/nftables-proxy/utils/nft-rule-validator.d.ts +59 -0
  30. package/dist_ts/proxies/nftables-proxy/utils/nft-rule-validator.js +130 -0
  31. package/dist_ts/proxies/smart-proxy/certificate-manager.js +4 -3
  32. package/dist_ts/proxies/smart-proxy/connection-manager.d.ts +13 -2
  33. package/dist_ts/proxies/smart-proxy/connection-manager.js +16 -6
  34. package/dist_ts/proxies/smart-proxy/http-proxy-bridge.js +35 -10
  35. package/dist_ts/proxies/smart-proxy/index.d.ts +5 -10
  36. package/dist_ts/proxies/smart-proxy/index.js +7 -13
  37. package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +5 -3
  38. package/dist_ts/proxies/smart-proxy/route-connection-handler.d.ts +17 -0
  39. package/dist_ts/proxies/smart-proxy/route-connection-handler.js +72 -9
  40. package/dist_ts/proxies/smart-proxy/route-preprocessor.d.ts +37 -0
  41. package/dist_ts/proxies/smart-proxy/route-preprocessor.js +103 -0
  42. package/dist_ts/proxies/smart-proxy/rust-binary-locator.d.ts +23 -0
  43. package/dist_ts/proxies/smart-proxy/rust-binary-locator.js +104 -0
  44. package/dist_ts/proxies/smart-proxy/rust-metrics-adapter.d.ts +74 -0
  45. package/dist_ts/proxies/smart-proxy/rust-metrics-adapter.js +146 -0
  46. package/dist_ts/proxies/smart-proxy/rust-proxy-bridge.d.ts +49 -0
  47. package/dist_ts/proxies/smart-proxy/rust-proxy-bridge.js +259 -0
  48. package/dist_ts/proxies/smart-proxy/security-manager.d.ts +14 -12
  49. package/dist_ts/proxies/smart-proxy/security-manager.js +80 -74
  50. package/dist_ts/proxies/smart-proxy/smart-proxy.d.ts +39 -157
  51. package/dist_ts/proxies/smart-proxy/smart-proxy.js +224 -622
  52. package/dist_ts/proxies/smart-proxy/socket-handler-server.d.ts +45 -0
  53. package/dist_ts/proxies/smart-proxy/socket-handler-server.js +253 -0
  54. package/dist_ts/proxies/smart-proxy/tls-manager.d.ts +2 -9
  55. package/dist_ts/proxies/smart-proxy/tls-manager.js +3 -26
  56. package/dist_ts/proxies/smart-proxy/utils/index.d.ts +1 -1
  57. package/dist_ts/proxies/smart-proxy/utils/index.js +3 -4
  58. package/dist_ts/proxies/smart-proxy/utils/route-helpers/api-helpers.d.ts +49 -0
  59. package/dist_ts/proxies/smart-proxy/utils/route-helpers/api-helpers.js +108 -0
  60. package/dist_ts/proxies/smart-proxy/utils/route-helpers/dynamic-helpers.d.ts +57 -0
  61. package/dist_ts/proxies/smart-proxy/utils/route-helpers/dynamic-helpers.js +89 -0
  62. package/dist_ts/proxies/smart-proxy/utils/route-helpers/http-helpers.d.ts +17 -0
  63. package/dist_ts/proxies/smart-proxy/utils/route-helpers/http-helpers.js +32 -0
  64. package/dist_ts/proxies/smart-proxy/utils/route-helpers/https-helpers.d.ts +68 -0
  65. package/dist_ts/proxies/smart-proxy/utils/route-helpers/https-helpers.js +117 -0
  66. package/dist_ts/proxies/smart-proxy/utils/route-helpers/index.d.ts +17 -0
  67. package/dist_ts/proxies/smart-proxy/utils/route-helpers/index.js +27 -0
  68. package/dist_ts/proxies/smart-proxy/utils/route-helpers/load-balancer-helpers.d.ts +63 -0
  69. package/dist_ts/proxies/smart-proxy/utils/route-helpers/load-balancer-helpers.js +105 -0
  70. package/dist_ts/proxies/smart-proxy/utils/route-helpers/nftables-helpers.d.ts +83 -0
  71. package/dist_ts/proxies/smart-proxy/utils/route-helpers/nftables-helpers.js +126 -0
  72. package/dist_ts/proxies/smart-proxy/utils/route-helpers/security-helpers.d.ts +47 -0
  73. package/dist_ts/proxies/smart-proxy/utils/route-helpers/security-helpers.js +66 -0
  74. package/dist_ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.d.ts +70 -0
  75. package/dist_ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.js +287 -0
  76. package/dist_ts/proxies/smart-proxy/utils/route-helpers/websocket-helpers.d.ts +46 -0
  77. package/dist_ts/proxies/smart-proxy/utils/route-helpers/websocket-helpers.js +67 -0
  78. package/dist_ts/proxies/smart-proxy/utils/route-helpers.d.ts +4 -457
  79. package/dist_ts/proxies/smart-proxy/utils/route-helpers.js +6 -950
  80. package/dist_ts/proxies/smart-proxy/utils/route-utils.js +2 -2
  81. package/dist_ts/proxies/smart-proxy/utils/route-validator.d.ts +67 -1
  82. package/dist_ts/proxies/smart-proxy/utils/route-validator.js +251 -3
  83. package/dist_ts/routing/index.d.ts +1 -1
  84. package/dist_ts/routing/index.js +3 -3
  85. package/dist_ts/routing/models/http-types.d.ts +119 -4
  86. package/dist_ts/routing/models/http-types.js +93 -5
  87. package/npmextra.json +12 -6
  88. package/package.json +34 -24
  89. package/readme.hints.md +184 -1
  90. package/readme.md +580 -266
  91. package/ts/00_commitinfo_data.ts +1 -1
  92. package/ts/core/utils/shared-security-manager.ts +98 -13
  93. package/ts/index.ts +4 -12
  94. package/ts/protocols/common/fragment-handler.ts +4 -0
  95. package/ts/proxies/index.ts +1 -9
  96. package/ts/proxies/nftables-proxy/index.ts +1 -0
  97. package/ts/proxies/nftables-proxy/nftables-proxy.ts +116 -290
  98. package/ts/proxies/nftables-proxy/utils/index.ts +38 -0
  99. package/ts/proxies/nftables-proxy/utils/nft-command-executor.ts +162 -0
  100. package/ts/proxies/nftables-proxy/utils/nft-port-spec-normalizer.ts +125 -0
  101. package/ts/proxies/nftables-proxy/utils/nft-rule-validator.ts +156 -0
  102. package/ts/proxies/smart-proxy/index.ts +6 -13
  103. package/ts/proxies/smart-proxy/models/interfaces.ts +6 -5
  104. package/ts/proxies/smart-proxy/route-preprocessor.ts +122 -0
  105. package/ts/proxies/smart-proxy/rust-binary-locator.ts +112 -0
  106. package/ts/proxies/smart-proxy/rust-metrics-adapter.ts +161 -0
  107. package/ts/proxies/smart-proxy/rust-proxy-bridge.ts +310 -0
  108. package/ts/proxies/smart-proxy/smart-proxy.ts +282 -800
  109. package/ts/proxies/smart-proxy/socket-handler-server.ts +279 -0
  110. package/ts/proxies/smart-proxy/utils/index.ts +3 -5
  111. package/ts/proxies/smart-proxy/utils/route-helpers/api-helpers.ts +144 -0
  112. package/ts/proxies/smart-proxy/utils/route-helpers/dynamic-helpers.ts +124 -0
  113. package/ts/proxies/smart-proxy/utils/route-helpers/http-helpers.ts +40 -0
  114. package/ts/proxies/smart-proxy/utils/route-helpers/https-helpers.ts +163 -0
  115. package/ts/proxies/smart-proxy/utils/route-helpers/index.ts +62 -0
  116. package/ts/proxies/smart-proxy/utils/route-helpers/load-balancer-helpers.ts +154 -0
  117. package/ts/proxies/smart-proxy/utils/route-helpers/nftables-helpers.ts +202 -0
  118. package/ts/proxies/smart-proxy/utils/route-helpers/security-helpers.ts +96 -0
  119. package/ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.ts +337 -0
  120. package/ts/proxies/smart-proxy/utils/route-helpers/websocket-helpers.ts +98 -0
  121. package/ts/proxies/smart-proxy/utils/route-helpers.ts +5 -1302
  122. package/ts/proxies/smart-proxy/utils/route-utils.ts +1 -1
  123. package/ts/proxies/smart-proxy/utils/route-validator.ts +274 -4
  124. package/ts/routing/index.ts +2 -2
  125. package/ts/routing/models/http-types.ts +147 -4
  126. package/ts/proxies/http-proxy/certificate-manager.ts +0 -244
  127. package/ts/proxies/http-proxy/connection-pool.ts +0 -228
  128. package/ts/proxies/http-proxy/context-creator.ts +0 -145
  129. package/ts/proxies/http-proxy/function-cache.ts +0 -279
  130. package/ts/proxies/http-proxy/handlers/index.ts +0 -5
  131. package/ts/proxies/http-proxy/http-proxy.ts +0 -675
  132. package/ts/proxies/http-proxy/http-request-handler.ts +0 -331
  133. package/ts/proxies/http-proxy/http2-request-handler.ts +0 -255
  134. package/ts/proxies/http-proxy/index.ts +0 -13
  135. package/ts/proxies/http-proxy/models/http-types.ts +0 -148
  136. package/ts/proxies/http-proxy/models/index.ts +0 -5
  137. package/ts/proxies/http-proxy/models/types.ts +0 -125
  138. package/ts/proxies/http-proxy/request-handler.ts +0 -878
  139. package/ts/proxies/http-proxy/security-manager.ts +0 -433
  140. package/ts/proxies/http-proxy/websocket-handler.ts +0 -581
  141. package/ts/proxies/smart-proxy/acme-state-manager.ts +0 -112
  142. package/ts/proxies/smart-proxy/cert-store.ts +0 -92
  143. package/ts/proxies/smart-proxy/certificate-manager.ts +0 -894
  144. package/ts/proxies/smart-proxy/connection-manager.ts +0 -796
  145. package/ts/proxies/smart-proxy/http-proxy-bridge.ts +0 -187
  146. package/ts/proxies/smart-proxy/metrics-collector.ts +0 -453
  147. package/ts/proxies/smart-proxy/nftables-manager.ts +0 -271
  148. package/ts/proxies/smart-proxy/port-manager.ts +0 -358
  149. package/ts/proxies/smart-proxy/route-connection-handler.ts +0 -1640
  150. package/ts/proxies/smart-proxy/route-orchestrator.ts +0 -297
  151. package/ts/proxies/smart-proxy/security-manager.ts +0 -257
  152. package/ts/proxies/smart-proxy/throughput-tracker.ts +0 -138
  153. package/ts/proxies/smart-proxy/timeout-manager.ts +0 -196
  154. package/ts/proxies/smart-proxy/tls-manager.ts +0 -207
  155. package/ts/proxies/smart-proxy/utils/route-validators.ts +0 -283
@@ -0,0 +1,337 @@
1
+ /**
2
+ * Socket Handler Functions
3
+ *
4
+ * This module provides pre-built socket handlers for common use cases
5
+ * like echoing, proxying, HTTP responses, and redirects.
6
+ */
7
+
8
+ import * as plugins from '../../../../plugins.js';
9
+ import type { IRouteConfig, TPortRange, IRouteContext } from '../../models/route-types.js';
10
+ import { ProtocolDetector } from '../../../../detection/index.js';
11
+ import { createSocketTracker } from '../../../../core/utils/socket-tracker.js';
12
+
13
+ /**
14
+ * Pre-built socket handlers for common use cases
15
+ */
16
+ export const SocketHandlers = {
17
+ /**
18
+ * Simple echo server handler
19
+ */
20
+ echo: (socket: plugins.net.Socket, context: IRouteContext) => {
21
+ socket.write('ECHO SERVER READY\n');
22
+ socket.on('data', data => socket.write(data));
23
+ },
24
+
25
+ /**
26
+ * TCP proxy handler
27
+ */
28
+ proxy: (targetHost: string, targetPort: number) => (socket: plugins.net.Socket, context: IRouteContext) => {
29
+ const target = plugins.net.connect(targetPort, targetHost);
30
+ socket.pipe(target);
31
+ target.pipe(socket);
32
+ socket.on('close', () => target.destroy());
33
+ target.on('close', () => socket.destroy());
34
+ target.on('error', (err) => {
35
+ console.error('Proxy target error:', err);
36
+ socket.destroy();
37
+ });
38
+ },
39
+
40
+ /**
41
+ * Line-based protocol handler
42
+ */
43
+ lineProtocol: (handler: (line: string, socket: plugins.net.Socket) => void) => (socket: plugins.net.Socket, context: IRouteContext) => {
44
+ let buffer = '';
45
+ socket.on('data', (data) => {
46
+ buffer += data.toString();
47
+ const lines = buffer.split('\n');
48
+ buffer = lines.pop() || '';
49
+ lines.forEach(line => {
50
+ if (line.trim()) {
51
+ handler(line.trim(), socket);
52
+ }
53
+ });
54
+ });
55
+ },
56
+
57
+ /**
58
+ * Simple HTTP response handler (for testing)
59
+ */
60
+ httpResponse: (statusCode: number, body: string) => (socket: plugins.net.Socket, context: IRouteContext) => {
61
+ const response = [
62
+ `HTTP/1.1 ${statusCode} ${statusCode === 200 ? 'OK' : 'Error'}`,
63
+ 'Content-Type: text/plain',
64
+ `Content-Length: ${body.length}`,
65
+ 'Connection: close',
66
+ '',
67
+ body
68
+ ].join('\r\n');
69
+
70
+ socket.write(response);
71
+ socket.end();
72
+ },
73
+
74
+ /**
75
+ * Block connection immediately
76
+ */
77
+ block: (message?: string) => (socket: plugins.net.Socket, context: IRouteContext) => {
78
+ const finalMessage = message || `Connection blocked from ${context.clientIp}`;
79
+ if (finalMessage) {
80
+ socket.write(finalMessage);
81
+ }
82
+ socket.end();
83
+ },
84
+
85
+ /**
86
+ * HTTP block response
87
+ */
88
+ httpBlock: (statusCode: number = 403, message?: string) => (socket: plugins.net.Socket, context: IRouteContext) => {
89
+ const defaultMessage = `Access forbidden for ${context.domain || context.clientIp}`;
90
+ const finalMessage = message || defaultMessage;
91
+
92
+ const response = [
93
+ `HTTP/1.1 ${statusCode} ${finalMessage}`,
94
+ 'Content-Type: text/plain',
95
+ `Content-Length: ${finalMessage.length}`,
96
+ 'Connection: close',
97
+ '',
98
+ finalMessage
99
+ ].join('\r\n');
100
+
101
+ socket.write(response);
102
+ socket.end();
103
+ },
104
+
105
+ /**
106
+ * HTTP redirect handler
107
+ * Uses the centralized detection module for HTTP parsing
108
+ */
109
+ httpRedirect: (locationTemplate: string, statusCode: number = 301) => (socket: plugins.net.Socket, context: IRouteContext) => {
110
+ 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
+
123
+ if (detectionResult.protocol === 'http' && detectionResult.connectionInfo.path) {
124
+ const method = detectionResult.connectionInfo.method || 'GET';
125
+ const path = detectionResult.connectionInfo.path || '/';
126
+
127
+ const domain = context.domain || 'localhost';
128
+ const port = context.port;
129
+
130
+ let finalLocation = locationTemplate
131
+ .replace('{domain}', domain)
132
+ .replace('{port}', String(port))
133
+ .replace('{path}', path)
134
+ .replace('{clientIp}', context.clientIp);
135
+
136
+ const message = `Redirecting to ${finalLocation}`;
137
+ const response = [
138
+ `HTTP/1.1 ${statusCode} ${statusCode === 301 ? 'Moved Permanently' : 'Found'}`,
139
+ `Location: ${finalLocation}`,
140
+ 'Content-Type: text/plain',
141
+ `Content-Length: ${message.length}`,
142
+ 'Connection: close',
143
+ '',
144
+ message
145
+ ].join('\r\n');
146
+
147
+ socket.write(response);
148
+ } else {
149
+ // Not a valid HTTP request, close connection
150
+ socket.write('HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n');
151
+ }
152
+
153
+ socket.end();
154
+ // Clean up detection state
155
+ ProtocolDetector.cleanupConnections();
156
+ // Clean up all tracked resources
157
+ tracker.cleanup();
158
+ };
159
+
160
+ // Use tracker to manage the listener
161
+ socket.once('data', handleData);
162
+
163
+ tracker.addListener('error', (err) => {
164
+ tracker.safeDestroy(err);
165
+ });
166
+
167
+ tracker.addListener('close', () => {
168
+ tracker.cleanup();
169
+ });
170
+ },
171
+
172
+ /**
173
+ * HTTP server handler for ACME challenges and other HTTP needs
174
+ * Uses the centralized detection module for HTTP parsing
175
+ */
176
+ 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
+ const tracker = createSocketTracker(socket);
178
+ let requestParsed = false;
179
+ let responseTimer: NodeJS.Timeout | null = null;
180
+ const connectionId = ProtocolDetector.createConnectionId({
181
+ socketId: context.connectionId || `${Date.now()}-${Math.random()}`
182
+ });
183
+
184
+ const processData = async (data: Buffer) => {
185
+ if (requestParsed) return; // Only handle the first request
186
+
187
+ // Use HttpDetector for parsing
188
+ const detectionResult = await ProtocolDetector.detectWithConnectionTracking(
189
+ data,
190
+ connectionId,
191
+ { extractFullHeaders: true }
192
+ );
193
+
194
+ if (detectionResult.protocol !== 'http' || !detectionResult.isComplete) {
195
+ // Not a complete HTTP request yet
196
+ return;
197
+ }
198
+
199
+ requestParsed = true;
200
+ // Remove data listener after parsing request
201
+ socket.removeListener('data', processData);
202
+ const connInfo = detectionResult.connectionInfo;
203
+
204
+ // Create request object from detection result
205
+ const req = {
206
+ method: connInfo.method || 'GET',
207
+ url: connInfo.path || '/',
208
+ headers: connInfo.headers || {},
209
+ body: detectionResult.remainingBuffer?.toString() || ''
210
+ };
211
+
212
+ // Create response object
213
+ let statusCode = 200;
214
+ const responseHeaders: Record<string, string> = {};
215
+ let ended = false;
216
+
217
+ const res = {
218
+ status: (code: number) => {
219
+ statusCode = code;
220
+ },
221
+ header: (name: string, value: string) => {
222
+ responseHeaders[name] = value;
223
+ },
224
+ send: (data: string) => {
225
+ if (ended) return;
226
+ ended = true;
227
+
228
+ // Clear response timer since we're sending now
229
+ if (responseTimer) {
230
+ clearTimeout(responseTimer);
231
+ responseTimer = null;
232
+ }
233
+
234
+ if (!responseHeaders['content-type']) {
235
+ responseHeaders['content-type'] = 'text/plain';
236
+ }
237
+ responseHeaders['content-length'] = String(data.length);
238
+ responseHeaders['connection'] = 'close';
239
+
240
+ const statusText = statusCode === 200 ? 'OK' :
241
+ statusCode === 404 ? 'Not Found' :
242
+ statusCode === 500 ? 'Internal Server Error' : 'Response';
243
+
244
+ let response = `HTTP/1.1 ${statusCode} ${statusText}\r\n`;
245
+ for (const [name, value] of Object.entries(responseHeaders)) {
246
+ response += `${name}: ${value}\r\n`;
247
+ }
248
+ response += '\r\n';
249
+ response += data;
250
+
251
+ socket.write(response);
252
+ socket.end();
253
+ },
254
+ end: () => {
255
+ if (ended) return;
256
+ ended = true;
257
+ socket.write('HTTP/1.1 200 OK\r\nContent-Length: 0\r\nConnection: close\r\n\r\n');
258
+ socket.end();
259
+ }
260
+ };
261
+
262
+ try {
263
+ handler(req, res);
264
+ // Ensure response is sent even if handler doesn't call send()
265
+ responseTimer = setTimeout(() => {
266
+ if (!ended) {
267
+ res.send('');
268
+ }
269
+ responseTimer = null;
270
+ }, 1000);
271
+ // Track and unref the timer
272
+ tracker.addTimer(responseTimer);
273
+ } catch (error) {
274
+ if (!ended) {
275
+ res.status(500);
276
+ res.send('Internal Server Error');
277
+ }
278
+ // Use safeDestroy for error cases
279
+ tracker.safeDestroy(error instanceof Error ? error : new Error('Handler error'));
280
+ }
281
+ };
282
+
283
+ // Use tracker to manage listeners
284
+ tracker.addListener('data', processData);
285
+
286
+ tracker.addListener('error', (err) => {
287
+ if (!requestParsed) {
288
+ tracker.safeDestroy(err);
289
+ }
290
+ });
291
+
292
+ tracker.addListener('close', () => {
293
+ // Clear any pending response timer
294
+ if (responseTimer) {
295
+ clearTimeout(responseTimer);
296
+ responseTimer = null;
297
+ }
298
+ // Clean up detection state
299
+ ProtocolDetector.cleanupConnections();
300
+ // Clean up all tracked resources
301
+ tracker.cleanup();
302
+ });
303
+ }
304
+ };
305
+
306
+ /**
307
+ * 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
+ export function createSocketHandlerRoute(
315
+ domains: string | string[],
316
+ ports: TPortRange,
317
+ handler: (socket: plugins.net.Socket) => void | Promise<void>,
318
+ options: {
319
+ name?: string;
320
+ priority?: number;
321
+ path?: string;
322
+ } = {}
323
+ ): IRouteConfig {
324
+ return {
325
+ name: options.name || 'socket-handler-route',
326
+ priority: options.priority !== undefined ? options.priority : 50,
327
+ match: {
328
+ domains,
329
+ ports,
330
+ ...(options.path && { path: options.path })
331
+ },
332
+ action: {
333
+ type: 'socket-handler',
334
+ socketHandler: handler
335
+ }
336
+ };
337
+ }
@@ -0,0 +1,98 @@
1
+ /**
2
+ * WebSocket Route Helper Functions
3
+ *
4
+ * This module provides utility functions for creating WebSocket route configurations.
5
+ */
6
+
7
+ import type { IRouteConfig, IRouteMatch, IRouteAction } from '../../models/route-types.js';
8
+
9
+ /**
10
+ * Create a WebSocket route configuration
11
+ * @param domains Domain(s) to match
12
+ * @param targetOrPath Target server OR WebSocket path (legacy)
13
+ * @param targetOrOptions Target server (legacy) OR options
14
+ * @param options Additional route options (legacy)
15
+ * @returns Route configuration object
16
+ */
17
+ export function createWebSocketRoute(
18
+ domains: string | string[],
19
+ targetOrPath: { host: string | string[]; port: number } | string,
20
+ targetOrOptions?: { host: string | string[]; port: number } | {
21
+ useTls?: boolean;
22
+ certificate?: 'auto' | { key: string; cert: string };
23
+ path?: string;
24
+ httpPort?: number | number[];
25
+ httpsPort?: number | number[];
26
+ pingInterval?: number;
27
+ pingTimeout?: number;
28
+ name?: string;
29
+ [key: string]: any;
30
+ },
31
+ options?: {
32
+ useTls?: boolean;
33
+ certificate?: 'auto' | { key: string; cert: string };
34
+ httpPort?: number | number[];
35
+ httpsPort?: number | number[];
36
+ pingInterval?: number;
37
+ pingTimeout?: number;
38
+ name?: string;
39
+ [key: string]: any;
40
+ }
41
+ ): IRouteConfig {
42
+ // Handle different signatures
43
+ let target: { host: string | string[]; port: number };
44
+ let wsPath: string;
45
+ let finalOptions: any;
46
+
47
+ if (typeof targetOrPath === 'string') {
48
+ // Legacy signature: (domains, path, target, options)
49
+ wsPath = targetOrPath;
50
+ target = targetOrOptions as { host: string | string[]; port: number };
51
+ finalOptions = options || {};
52
+ } else {
53
+ // New signature: (domains, target, options)
54
+ target = targetOrPath;
55
+ finalOptions = (targetOrOptions as any) || {};
56
+ wsPath = finalOptions.path || '/ws';
57
+ }
58
+
59
+ // Normalize WebSocket path
60
+ const normalizedPath = wsPath.startsWith('/') ? wsPath : `/${wsPath}`;
61
+
62
+ // Create route match
63
+ const match: IRouteMatch = {
64
+ ports: finalOptions.useTls
65
+ ? (finalOptions.httpsPort || 443)
66
+ : (finalOptions.httpPort || 80),
67
+ domains,
68
+ path: normalizedPath
69
+ };
70
+
71
+ // Create route action
72
+ const action: IRouteAction = {
73
+ type: 'forward',
74
+ targets: [target],
75
+ websocket: {
76
+ enabled: true,
77
+ pingInterval: finalOptions.pingInterval || 30000, // 30 seconds
78
+ pingTimeout: finalOptions.pingTimeout || 5000 // 5 seconds
79
+ }
80
+ };
81
+
82
+ // Add TLS configuration if using HTTPS
83
+ if (finalOptions.useTls) {
84
+ action.tls = {
85
+ mode: 'terminate',
86
+ certificate: finalOptions.certificate || 'auto'
87
+ };
88
+ }
89
+
90
+ // Create the route config
91
+ return {
92
+ match,
93
+ action,
94
+ name: finalOptions.name || `WebSocket Route ${normalizedPath} for ${Array.isArray(domains) ? domains.join(', ') : domains}`,
95
+ priority: finalOptions.priority || 100, // Higher priority for WebSocket routes
96
+ ...finalOptions
97
+ };
98
+ }