@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
@@ -1,331 +0,0 @@
1
- import * as plugins from '../../plugins.js';
2
- import '../../core/models/socket-augmentation.js';
3
- import type { IHttpRouteContext, IRouteContext } from '../../core/models/route-context.js';
4
- import type { ILogger } from './models/types.js';
5
- import type { IMetricsTracker } from './request-handler.js';
6
- import type { IRouteConfig } from '../smart-proxy/models/route-types.js';
7
- import { TemplateUtils } from '../../core/utils/template-utils.js';
8
-
9
- /**
10
- * HTTP Request Handler Helper - handles requests with specific destinations
11
- * This is a helper class for the main RequestHandler
12
- */
13
- export class HttpRequestHandler {
14
- /**
15
- * Handle HTTP request with a specific destination
16
- */
17
- public static async handleHttpRequestWithDestination(
18
- req: plugins.http.IncomingMessage,
19
- res: plugins.http.ServerResponse,
20
- destination: { host: string, port: number },
21
- routeContext: IHttpRouteContext,
22
- startTime: number,
23
- logger: ILogger,
24
- metricsTracker?: IMetricsTracker | null,
25
- route?: IRouteConfig
26
- ): Promise<void> {
27
- try {
28
- // Apply URL rewriting if route config is provided
29
- if (route) {
30
- HttpRequestHandler.applyUrlRewriting(req, route, routeContext, logger);
31
- HttpRequestHandler.applyRouteHeaderModifications(route, req, res, logger);
32
- }
33
-
34
- // Create options for the proxy request
35
- const options: plugins.http.RequestOptions = {
36
- hostname: destination.host,
37
- port: destination.port,
38
- path: req.url,
39
- method: req.method,
40
- headers: { ...req.headers }
41
- };
42
-
43
- // Optionally rewrite host header to match target
44
- if (options.headers && 'host' in options.headers) {
45
- // Only apply if host header rewrite is enabled or not explicitly disabled
46
- const shouldRewriteHost = route?.action.options?.rewriteHostHeader !== false;
47
- if (shouldRewriteHost) {
48
- // Safely cast to OutgoingHttpHeaders to access host property
49
- (options.headers as plugins.http.OutgoingHttpHeaders).host = `${destination.host}:${destination.port}`;
50
- }
51
- }
52
-
53
- logger.debug(
54
- `Proxying request to ${destination.host}:${destination.port}${req.url}`,
55
- { method: req.method }
56
- );
57
-
58
- // Create proxy request
59
- const proxyReq = plugins.http.request(options, (proxyRes) => {
60
- // Copy status code
61
- res.statusCode = proxyRes.statusCode || 500;
62
-
63
- // Copy headers from proxy response to client response
64
- for (const [key, value] of Object.entries(proxyRes.headers)) {
65
- if (value !== undefined) {
66
- res.setHeader(key, value);
67
- }
68
- }
69
-
70
- // Apply response header modifications if route config is provided
71
- if (route && route.headers?.response) {
72
- HttpRequestHandler.applyResponseHeaderModifications(route, res, logger, routeContext);
73
- }
74
-
75
- // Pipe proxy response to client response
76
- proxyRes.pipe(res);
77
-
78
- // Increment served requests counter when the response finishes
79
- res.on('finish', () => {
80
- if (metricsTracker) {
81
- metricsTracker.incrementRequestsServed();
82
- }
83
-
84
- // Log the completed request
85
- const duration = Date.now() - startTime;
86
- logger.debug(
87
- `Request completed in ${duration}ms: ${req.method} ${req.url} ${res.statusCode}`,
88
- { duration, statusCode: res.statusCode }
89
- );
90
- });
91
- });
92
-
93
- // Handle proxy request errors
94
- proxyReq.on('error', (error) => {
95
- const duration = Date.now() - startTime;
96
- logger.error(
97
- `Proxy error for ${req.method} ${req.url}: ${error.message}`,
98
- { duration, error: error.message }
99
- );
100
-
101
- // Increment failed requests counter
102
- if (metricsTracker) {
103
- metricsTracker.incrementFailedRequests();
104
- }
105
-
106
- // Check if headers have already been sent
107
- if (!res.headersSent) {
108
- res.statusCode = 502;
109
- res.end(`Bad Gateway: ${error.message}`);
110
- } else {
111
- // If headers already sent, just close the connection
112
- res.end();
113
- }
114
- });
115
-
116
- // Pipe request body to proxy request and handle client-side errors
117
- req.pipe(proxyReq);
118
-
119
- // Handle client disconnection
120
- req.on('error', (error) => {
121
- logger.debug(`Client connection error: ${error.message}`);
122
- proxyReq.destroy();
123
-
124
- // Increment failed requests counter on client errors
125
- if (metricsTracker) {
126
- metricsTracker.incrementFailedRequests();
127
- }
128
- });
129
-
130
- // Handle response errors
131
- res.on('error', (error) => {
132
- logger.debug(`Response error: ${error.message}`);
133
- proxyReq.destroy();
134
-
135
- // Increment failed requests counter on response errors
136
- if (metricsTracker) {
137
- metricsTracker.incrementFailedRequests();
138
- }
139
- });
140
- } catch (error) {
141
- // Handle any unexpected errors
142
- logger.error(
143
- `Unexpected error handling request: ${error.message}`,
144
- { error: error.stack }
145
- );
146
-
147
- // Increment failed requests counter
148
- if (metricsTracker) {
149
- metricsTracker.incrementFailedRequests();
150
- }
151
-
152
- if (!res.headersSent) {
153
- res.statusCode = 500;
154
- res.end('Internal Server Error');
155
- } else {
156
- res.end();
157
- }
158
- }
159
- }
160
-
161
- /**
162
- * Apply URL rewriting based on route configuration
163
- * Implements Phase 5.2: URL rewriting using route context
164
- *
165
- * @param req The request with the URL to rewrite
166
- * @param route The route configuration containing rewrite rules
167
- * @param routeContext Context for template variable resolution
168
- * @param logger Logger for debugging information
169
- * @returns True if URL was rewritten, false otherwise
170
- */
171
- private static applyUrlRewriting(
172
- req: plugins.http.IncomingMessage,
173
- route: IRouteConfig,
174
- routeContext: IHttpRouteContext,
175
- logger: ILogger
176
- ): boolean {
177
- // Check if route has URL rewriting configuration
178
- if (!route.action.advanced?.urlRewrite) {
179
- return false;
180
- }
181
-
182
- const rewriteConfig = route.action.advanced.urlRewrite;
183
-
184
- // Store original URL for logging
185
- const originalUrl = req.url;
186
-
187
- if (rewriteConfig.pattern && rewriteConfig.target) {
188
- try {
189
- // Create a RegExp from the pattern with optional flags
190
- const regex = new RegExp(rewriteConfig.pattern, rewriteConfig.flags || '');
191
-
192
- // Apply rewriting with template variable resolution
193
- let target = rewriteConfig.target;
194
-
195
- // Replace template variables in target with values from context
196
- target = TemplateUtils.resolveTemplateVariables(target, routeContext);
197
-
198
- // If onlyRewritePath is set, split URL into path and query parts
199
- if (rewriteConfig.onlyRewritePath && req.url) {
200
- const [path, query] = req.url.split('?');
201
- const rewrittenPath = path.replace(regex, target);
202
- req.url = query ? `${rewrittenPath}?${query}` : rewrittenPath;
203
- } else {
204
- // Perform the replacement on the entire URL
205
- req.url = req.url?.replace(regex, target);
206
- }
207
-
208
- logger.debug(`URL rewritten: ${originalUrl} -> ${req.url}`);
209
- return true;
210
- } catch (err) {
211
- logger.error(`Error in URL rewriting: ${err}`);
212
- return false;
213
- }
214
- }
215
-
216
- return false;
217
- }
218
-
219
- /**
220
- * Apply header modifications from route configuration to request headers
221
- * Implements Phase 5.1: Route-based header manipulation for requests
222
- */
223
- private static applyRouteHeaderModifications(
224
- route: IRouteConfig,
225
- req: plugins.http.IncomingMessage,
226
- res: plugins.http.ServerResponse,
227
- logger: ILogger
228
- ): void {
229
- // Check if route has header modifications
230
- if (!route.headers) {
231
- return;
232
- }
233
-
234
- // Apply request header modifications (these will be sent to the backend)
235
- if (route.headers.request && req.headers) {
236
- // Create routing context for template resolution
237
- const routeContext: IRouteContext = {
238
- domain: req.headers.host as string || '',
239
- path: req.url || '',
240
- clientIp: req.socket.remoteAddress?.replace('::ffff:', '') || '',
241
- serverIp: req.socket.localAddress?.replace('::ffff:', '') || '',
242
- port: parseInt(req.socket.localPort?.toString() || '0', 10),
243
- isTls: !!req.socket.encrypted,
244
- headers: req.headers as Record<string, string>,
245
- timestamp: Date.now(),
246
- connectionId: `${Date.now()}-${Math.floor(Math.random() * 10000)}`,
247
- };
248
-
249
- for (const [key, value] of Object.entries(route.headers.request)) {
250
- // Skip if header already exists and we're not overriding
251
- if (req.headers[key.toLowerCase()] && !value.startsWith('!')) {
252
- continue;
253
- }
254
-
255
- // Handle special delete directive (!delete)
256
- if (value === '!delete') {
257
- delete req.headers[key.toLowerCase()];
258
- logger.debug(`Deleted request header: ${key}`);
259
- continue;
260
- }
261
-
262
- // Handle forced override (!value)
263
- let finalValue: string;
264
- if (value.startsWith('!')) {
265
- // Keep the ! but resolve any templates in the rest
266
- const templateValue = value.substring(1);
267
- finalValue = '!' + TemplateUtils.resolveTemplateVariables(templateValue, routeContext);
268
- } else {
269
- // Resolve templates in the entire value
270
- finalValue = TemplateUtils.resolveTemplateVariables(value, routeContext);
271
- }
272
-
273
- // Set the header
274
- req.headers[key.toLowerCase()] = finalValue;
275
- logger.debug(`Modified request header: ${key}=${finalValue}`);
276
- }
277
- }
278
- }
279
-
280
- /**
281
- * Apply header modifications from route configuration to response headers
282
- * Implements Phase 5.1: Route-based header manipulation for responses
283
- */
284
- private static applyResponseHeaderModifications(
285
- route: IRouteConfig,
286
- res: plugins.http.ServerResponse,
287
- logger: ILogger,
288
- routeContext?: IRouteContext
289
- ): void {
290
- // Check if route has response header modifications
291
- if (!route.headers?.response) {
292
- return;
293
- }
294
-
295
- // Apply response header modifications
296
- for (const [key, value] of Object.entries(route.headers.response)) {
297
- // Skip if header already exists and we're not overriding
298
- if (res.hasHeader(key) && !value.startsWith('!')) {
299
- continue;
300
- }
301
-
302
- // Handle special delete directive (!delete)
303
- if (value === '!delete') {
304
- res.removeHeader(key);
305
- logger.debug(`Deleted response header: ${key}`);
306
- continue;
307
- }
308
-
309
- // Handle forced override (!value)
310
- let finalValue: string;
311
- if (value.startsWith('!') && value !== '!delete') {
312
- // Keep the ! but resolve any templates in the rest
313
- const templateValue = value.substring(1);
314
- finalValue = routeContext
315
- ? '!' + TemplateUtils.resolveTemplateVariables(templateValue, routeContext)
316
- : '!' + templateValue;
317
- } else {
318
- // Resolve templates in the entire value
319
- finalValue = routeContext
320
- ? TemplateUtils.resolveTemplateVariables(value, routeContext)
321
- : value;
322
- }
323
-
324
- // Set the header
325
- res.setHeader(key, finalValue);
326
- logger.debug(`Modified response header: ${key}=${finalValue}`);
327
- }
328
- }
329
-
330
- // Template resolution is now handled by the TemplateUtils class
331
- }
@@ -1,255 +0,0 @@
1
- import * as plugins from '../../plugins.js';
2
- import type { IHttpRouteContext } from '../../core/models/route-context.js';
3
- import type { ILogger } from './models/types.js';
4
- import type { IMetricsTracker } from './request-handler.js';
5
-
6
- /**
7
- * HTTP/2 Request Handler Helper - handles HTTP/2 streams with specific destinations
8
- * This is a helper class for the main RequestHandler
9
- */
10
- export class Http2RequestHandler {
11
- /**
12
- * Handle HTTP/2 stream with direct HTTP/2 backend
13
- */
14
- public static async handleHttp2WithHttp2Destination(
15
- stream: plugins.http2.ServerHttp2Stream,
16
- headers: plugins.http2.IncomingHttpHeaders,
17
- destination: { host: string, port: number },
18
- routeContext: IHttpRouteContext,
19
- sessions: Map<string, plugins.http2.ClientHttp2Session>,
20
- logger: ILogger,
21
- metricsTracker?: IMetricsTracker | null
22
- ): Promise<void> {
23
- const key = `${destination.host}:${destination.port}`;
24
-
25
- // Get or create a client HTTP/2 session
26
- let session = sessions.get(key);
27
- if (!session || session.closed || (session as any).destroyed) {
28
- try {
29
- // Connect to the backend HTTP/2 server
30
- session = plugins.http2.connect(`http://${destination.host}:${destination.port}`);
31
- sessions.set(key, session);
32
-
33
- // Handle session errors and cleanup
34
- session.on('error', (err) => {
35
- logger.error(`HTTP/2 session error to ${key}: ${err.message}`);
36
- sessions.delete(key);
37
- });
38
-
39
- session.on('close', () => {
40
- logger.debug(`HTTP/2 session closed to ${key}`);
41
- sessions.delete(key);
42
- });
43
- } catch (err) {
44
- logger.error(`Failed to establish HTTP/2 session to ${key}: ${err.message}`);
45
- stream.respond({ ':status': 502 });
46
- stream.end('Bad Gateway: Failed to establish connection to backend');
47
- if (metricsTracker) metricsTracker.incrementFailedRequests();
48
- return;
49
- }
50
- }
51
-
52
- try {
53
- // Build headers for backend HTTP/2 request
54
- const h2Headers: Record<string, any> = {
55
- ':method': headers[':method'],
56
- ':path': headers[':path'],
57
- ':authority': `${destination.host}:${destination.port}`
58
- };
59
-
60
- // Copy other headers, excluding pseudo-headers
61
- for (const [key, value] of Object.entries(headers)) {
62
- if (!key.startsWith(':') && typeof value === 'string') {
63
- h2Headers[key] = value;
64
- }
65
- }
66
-
67
- logger.debug(
68
- `Proxying HTTP/2 request to ${destination.host}:${destination.port}${headers[':path']}`,
69
- { method: headers[':method'] }
70
- );
71
-
72
- // Create HTTP/2 request stream to the backend
73
- const h2Stream = session.request(h2Headers);
74
-
75
- // Pipe client stream to backend stream
76
- stream.pipe(h2Stream);
77
-
78
- // Handle responses from the backend
79
- h2Stream.on('response', (responseHeaders) => {
80
- // Map status and headers to client response
81
- const resp: Record<string, any> = {
82
- ':status': responseHeaders[':status'] as number
83
- };
84
-
85
- // Copy non-pseudo headers
86
- for (const [key, value] of Object.entries(responseHeaders)) {
87
- if (!key.startsWith(':') && value !== undefined) {
88
- resp[key] = value;
89
- }
90
- }
91
-
92
- // Send headers to client
93
- stream.respond(resp);
94
-
95
- // Pipe backend response to client
96
- h2Stream.pipe(stream);
97
-
98
- // Track successful requests
99
- stream.on('end', () => {
100
- if (metricsTracker) metricsTracker.incrementRequestsServed();
101
- logger.debug(
102
- `HTTP/2 request completed: ${headers[':method']} ${headers[':path']} ${responseHeaders[':status']}`,
103
- { method: headers[':method'], status: responseHeaders[':status'] }
104
- );
105
- });
106
- });
107
-
108
- // Handle backend errors
109
- h2Stream.on('error', (err) => {
110
- logger.error(`HTTP/2 stream error: ${err.message}`);
111
-
112
- // Only send error response if headers haven't been sent
113
- if (!stream.headersSent) {
114
- stream.respond({ ':status': 502 });
115
- stream.end(`Bad Gateway: ${err.message}`);
116
- } else {
117
- stream.end();
118
- }
119
-
120
- if (metricsTracker) metricsTracker.incrementFailedRequests();
121
- });
122
-
123
- // Handle client stream errors
124
- stream.on('error', (err) => {
125
- logger.debug(`Client HTTP/2 stream error: ${err.message}`);
126
- h2Stream.destroy();
127
- if (metricsTracker) metricsTracker.incrementFailedRequests();
128
- });
129
-
130
- } catch (err: any) {
131
- logger.error(`Error handling HTTP/2 request: ${err.message}`);
132
-
133
- // Only send error response if headers haven't been sent
134
- if (!stream.headersSent) {
135
- stream.respond({ ':status': 500 });
136
- stream.end('Internal Server Error');
137
- } else {
138
- stream.end();
139
- }
140
-
141
- if (metricsTracker) metricsTracker.incrementFailedRequests();
142
- }
143
- }
144
-
145
- /**
146
- * Handle HTTP/2 stream with HTTP/1 backend
147
- */
148
- public static async handleHttp2WithHttp1Destination(
149
- stream: plugins.http2.ServerHttp2Stream,
150
- headers: plugins.http2.IncomingHttpHeaders,
151
- destination: { host: string, port: number },
152
- routeContext: IHttpRouteContext,
153
- logger: ILogger,
154
- metricsTracker?: IMetricsTracker | null
155
- ): Promise<void> {
156
- try {
157
- // Build headers for HTTP/1 proxy request, excluding HTTP/2 pseudo-headers
158
- const outboundHeaders: Record<string, string> = {};
159
- for (const [key, value] of Object.entries(headers)) {
160
- if (typeof key === 'string' && typeof value === 'string' && !key.startsWith(':')) {
161
- outboundHeaders[key] = value;
162
- }
163
- }
164
-
165
- // Always rewrite host header to match target
166
- outboundHeaders.host = `${destination.host}:${destination.port}`;
167
-
168
- logger.debug(
169
- `Proxying HTTP/2 request to HTTP/1 backend ${destination.host}:${destination.port}${headers[':path']}`,
170
- { method: headers[':method'] }
171
- );
172
-
173
- // Create HTTP/1 proxy request
174
- const proxyReq = plugins.http.request(
175
- {
176
- hostname: destination.host,
177
- port: destination.port,
178
- path: headers[':path'] as string,
179
- method: headers[':method'] as string,
180
- headers: outboundHeaders
181
- },
182
- (proxyRes) => {
183
- // Map status and headers back to HTTP/2
184
- const responseHeaders: Record<string, number | string | string[]> = {
185
- ':status': proxyRes.statusCode || 500
186
- };
187
-
188
- // Copy headers from HTTP/1 response to HTTP/2 response
189
- for (const [key, value] of Object.entries(proxyRes.headers)) {
190
- if (value !== undefined) {
191
- responseHeaders[key] = value as string | string[];
192
- }
193
- }
194
-
195
- // Send headers to client
196
- stream.respond(responseHeaders);
197
-
198
- // Pipe HTTP/1 response to HTTP/2 stream
199
- proxyRes.pipe(stream);
200
-
201
- // Clean up when client disconnects
202
- stream.on('close', () => proxyReq.destroy());
203
- stream.on('error', () => proxyReq.destroy());
204
-
205
- // Track successful requests
206
- stream.on('end', () => {
207
- if (metricsTracker) metricsTracker.incrementRequestsServed();
208
- logger.debug(
209
- `HTTP/2 to HTTP/1 request completed: ${headers[':method']} ${headers[':path']} ${proxyRes.statusCode}`,
210
- { method: headers[':method'], status: proxyRes.statusCode }
211
- );
212
- });
213
- }
214
- );
215
-
216
- // Handle proxy request errors
217
- proxyReq.on('error', (err) => {
218
- logger.error(`HTTP/1 proxy error: ${err.message}`);
219
-
220
- // Only send error response if headers haven't been sent
221
- if (!stream.headersSent) {
222
- stream.respond({ ':status': 502 });
223
- stream.end(`Bad Gateway: ${err.message}`);
224
- } else {
225
- stream.end();
226
- }
227
-
228
- if (metricsTracker) metricsTracker.incrementFailedRequests();
229
- });
230
-
231
- // Pipe client stream to proxy request
232
- stream.pipe(proxyReq);
233
-
234
- // Handle client stream errors
235
- stream.on('error', (err) => {
236
- logger.debug(`Client HTTP/2 stream error: ${err.message}`);
237
- proxyReq.destroy();
238
- if (metricsTracker) metricsTracker.incrementFailedRequests();
239
- });
240
-
241
- } catch (err: any) {
242
- logger.error(`Error handling HTTP/2 to HTTP/1 request: ${err.message}`);
243
-
244
- // Only send error response if headers haven't been sent
245
- if (!stream.headersSent) {
246
- stream.respond({ ':status': 500 });
247
- stream.end('Internal Server Error');
248
- } else {
249
- stream.end();
250
- }
251
-
252
- if (metricsTracker) metricsTracker.incrementFailedRequests();
253
- }
254
- }
255
- }
@@ -1,13 +0,0 @@
1
- /**
2
- * HttpProxy implementation
3
- */
4
- // Re-export models
5
- export * from './models/index.js';
6
-
7
- // Export HttpProxy and supporting classes
8
- export { HttpProxy } from './http-proxy.js';
9
- export { CertificateManager } from './certificate-manager.js';
10
- export { ConnectionPool } from './connection-pool.js';
11
- export { RequestHandler } from './request-handler.js';
12
- export type { IMetricsTracker, MetricsTracker } from './request-handler.js';
13
- export { WebSocketHandler } from './websocket-handler.js';