@push.rocks/smartproxy 19.5.19 → 19.5.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_ts/core/models/index.d.ts +2 -0
- package/dist_ts/core/models/index.js +3 -1
- package/dist_ts/core/models/socket-types.d.ts +14 -0
- package/dist_ts/core/models/socket-types.js +15 -0
- package/dist_ts/core/models/wrapped-socket.d.ts +34 -0
- package/dist_ts/core/models/wrapped-socket.js +82 -0
- package/dist_ts/core/routing/index.d.ts +11 -0
- package/dist_ts/core/routing/index.js +17 -0
- package/dist_ts/core/routing/matchers/domain.d.ts +34 -0
- package/dist_ts/core/routing/matchers/domain.js +91 -0
- package/dist_ts/core/routing/matchers/header.d.ts +32 -0
- package/dist_ts/core/routing/matchers/header.js +94 -0
- package/dist_ts/core/routing/matchers/index.d.ts +18 -0
- package/dist_ts/core/routing/matchers/index.js +20 -0
- package/dist_ts/core/routing/matchers/ip.d.ts +53 -0
- package/dist_ts/core/routing/matchers/ip.js +169 -0
- package/dist_ts/core/routing/matchers/path.d.ts +44 -0
- package/dist_ts/core/routing/matchers/path.js +148 -0
- package/dist_ts/core/routing/route-manager.d.ts +88 -0
- package/dist_ts/core/routing/route-manager.js +342 -0
- package/dist_ts/core/routing/route-utils.d.ts +28 -0
- package/dist_ts/core/routing/route-utils.js +67 -0
- package/dist_ts/core/routing/specificity.d.ts +30 -0
- package/dist_ts/core/routing/specificity.js +115 -0
- package/dist_ts/core/routing/types.d.ts +41 -0
- package/dist_ts/core/routing/types.js +5 -0
- package/dist_ts/core/utils/index.d.ts +0 -2
- package/dist_ts/core/utils/index.js +1 -3
- package/dist_ts/core/utils/route-manager.d.ts +0 -30
- package/dist_ts/core/utils/route-manager.js +6 -47
- package/dist_ts/core/utils/route-utils.d.ts +2 -68
- package/dist_ts/core/utils/route-utils.js +21 -218
- package/dist_ts/core/utils/security-utils.js +4 -4
- package/dist_ts/index.d.ts +2 -5
- package/dist_ts/index.js +5 -11
- package/dist_ts/proxies/http-proxy/http-proxy.d.ts +0 -1
- package/dist_ts/proxies/http-proxy/http-proxy.js +15 -60
- package/dist_ts/proxies/http-proxy/models/types.d.ts +0 -90
- package/dist_ts/proxies/http-proxy/models/types.js +1 -242
- package/dist_ts/proxies/http-proxy/request-handler.d.ts +3 -5
- package/dist_ts/proxies/http-proxy/request-handler.js +20 -171
- package/dist_ts/proxies/http-proxy/websocket-handler.d.ts +2 -5
- package/dist_ts/proxies/http-proxy/websocket-handler.js +15 -23
- package/dist_ts/proxies/index.d.ts +2 -2
- package/dist_ts/proxies/index.js +4 -3
- package/dist_ts/proxies/smart-proxy/connection-manager.d.ts +3 -1
- package/dist_ts/proxies/smart-proxy/connection-manager.js +15 -7
- package/dist_ts/proxies/smart-proxy/http-proxy-bridge.d.ts +2 -1
- package/dist_ts/proxies/smart-proxy/http-proxy-bridge.js +5 -2
- package/dist_ts/proxies/smart-proxy/index.d.ts +1 -1
- package/dist_ts/proxies/smart-proxy/index.js +2 -2
- package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +6 -2
- package/dist_ts/proxies/smart-proxy/route-connection-handler.d.ts +1 -1
- package/dist_ts/proxies/smart-proxy/route-connection-handler.js +48 -25
- package/dist_ts/proxies/smart-proxy/smart-proxy.d.ts +1 -1
- package/dist_ts/proxies/smart-proxy/smart-proxy.js +15 -4
- package/dist_ts/proxies/smart-proxy/utils/route-utils.js +10 -43
- package/dist_ts/routing/router/http-router.d.ts +89 -0
- package/dist_ts/routing/router/http-router.js +205 -0
- package/dist_ts/routing/router/index.d.ts +2 -5
- package/dist_ts/routing/router/index.js +3 -4
- package/package.json +1 -1
- package/readme.delete.md +187 -0
- package/readme.hints.md +189 -1
- package/readme.plan.md +621 -0
- package/readme.routing.md +341 -0
- package/ts/core/models/index.ts +2 -0
- package/ts/core/models/socket-types.ts +21 -0
- package/ts/core/models/wrapped-socket.ts +99 -0
- package/ts/core/routing/index.ts +21 -0
- package/ts/core/routing/matchers/domain.ts +119 -0
- package/ts/core/routing/matchers/header.ts +120 -0
- package/ts/core/routing/matchers/index.ts +22 -0
- package/ts/core/routing/matchers/ip.ts +207 -0
- package/ts/core/routing/matchers/path.ts +184 -0
- package/ts/core/{utils → routing}/route-manager.ts +7 -57
- package/ts/core/routing/route-utils.ts +88 -0
- package/ts/core/routing/specificity.ts +141 -0
- package/ts/core/routing/types.ts +49 -0
- package/ts/core/utils/index.ts +0 -2
- package/ts/core/utils/security-utils.ts +3 -7
- package/ts/index.ts +4 -14
- package/ts/proxies/http-proxy/http-proxy.ts +13 -68
- package/ts/proxies/http-proxy/models/types.ts +0 -324
- package/ts/proxies/http-proxy/request-handler.ts +15 -186
- package/ts/proxies/http-proxy/websocket-handler.ts +15 -26
- package/ts/proxies/index.ts +3 -2
- package/ts/proxies/smart-proxy/connection-manager.ts +15 -7
- package/ts/proxies/smart-proxy/http-proxy-bridge.ts +6 -2
- package/ts/proxies/smart-proxy/index.ts +1 -1
- package/ts/proxies/smart-proxy/models/interfaces.ts +8 -2
- package/ts/proxies/smart-proxy/route-connection-handler.ts +58 -30
- package/ts/proxies/smart-proxy/smart-proxy.ts +15 -3
- package/ts/proxies/smart-proxy/utils/route-utils.ts +11 -49
- package/ts/routing/router/http-router.ts +266 -0
- package/ts/routing/router/index.ts +3 -8
- package/readme.problems.md +0 -170
- package/ts/core/utils/route-utils.ts +0 -312
- package/ts/proxies/smart-proxy/route-manager.ts +0 -554
- package/ts/routing/router/proxy-router.ts +0 -437
- package/ts/routing/router/route-router.ts +0 -482
|
@@ -1,437 +0,0 @@
|
|
|
1
|
-
import * as plugins from '../../plugins.js';
|
|
2
|
-
import type { IReverseProxyConfig } from '../../proxies/http-proxy/models/types.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Optional path pattern configuration that can be added to proxy configs
|
|
6
|
-
*/
|
|
7
|
-
export interface PathPatternConfig {
|
|
8
|
-
pathPattern?: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
// Backward compatibility
|
|
12
|
-
export type IPathPatternConfig = PathPatternConfig;
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Interface for router result with additional metadata
|
|
16
|
-
*/
|
|
17
|
-
export interface RouterResult {
|
|
18
|
-
config: IReverseProxyConfig;
|
|
19
|
-
pathMatch?: string;
|
|
20
|
-
pathParams?: Record<string, string>;
|
|
21
|
-
pathRemainder?: string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Backward compatibility
|
|
25
|
-
export type IRouterResult = RouterResult;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Router for HTTP reverse proxy requests
|
|
29
|
-
*
|
|
30
|
-
* Supports the following domain matching patterns:
|
|
31
|
-
* - Exact matches: "example.com"
|
|
32
|
-
* - Wildcard subdomains: "*.example.com" (matches any subdomain of example.com)
|
|
33
|
-
* - TLD wildcards: "example.*" (matches example.com, example.org, etc.)
|
|
34
|
-
* - Complex wildcards: "*.lossless*" (matches any subdomain of any lossless domain)
|
|
35
|
-
* - Default fallback: "*" (matches any unmatched domain)
|
|
36
|
-
*
|
|
37
|
-
* Also supports path pattern matching for each domain:
|
|
38
|
-
* - Exact path: "/api/users"
|
|
39
|
-
* - Wildcard paths: "/api/*"
|
|
40
|
-
* - Path parameters: "/users/:id/profile"
|
|
41
|
-
*/
|
|
42
|
-
export class ProxyRouter {
|
|
43
|
-
// Store original configs for reference
|
|
44
|
-
private reverseProxyConfigs: IReverseProxyConfig[] = [];
|
|
45
|
-
// Default config to use when no match is found (optional)
|
|
46
|
-
private defaultConfig?: IReverseProxyConfig;
|
|
47
|
-
// Store path patterns separately since they're not in the original interface
|
|
48
|
-
private pathPatterns: Map<IReverseProxyConfig, string> = new Map();
|
|
49
|
-
// Logger interface
|
|
50
|
-
private logger: {
|
|
51
|
-
error: (message: string, data?: any) => void;
|
|
52
|
-
warn: (message: string, data?: any) => void;
|
|
53
|
-
info: (message: string, data?: any) => void;
|
|
54
|
-
debug: (message: string, data?: any) => void;
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
constructor(
|
|
58
|
-
configs?: IReverseProxyConfig[],
|
|
59
|
-
logger?: {
|
|
60
|
-
error: (message: string, data?: any) => void;
|
|
61
|
-
warn: (message: string, data?: any) => void;
|
|
62
|
-
info: (message: string, data?: any) => void;
|
|
63
|
-
debug: (message: string, data?: any) => void;
|
|
64
|
-
}
|
|
65
|
-
) {
|
|
66
|
-
this.logger = logger || console;
|
|
67
|
-
if (configs) {
|
|
68
|
-
this.setNewProxyConfigs(configs);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Sets a new set of reverse configs to be routed to
|
|
74
|
-
* @param reverseCandidatesArg Array of reverse proxy configurations
|
|
75
|
-
*/
|
|
76
|
-
public setNewProxyConfigs(reverseCandidatesArg: IReverseProxyConfig[]): void {
|
|
77
|
-
this.reverseProxyConfigs = [...reverseCandidatesArg];
|
|
78
|
-
|
|
79
|
-
// Find default config if any (config with "*" as hostname)
|
|
80
|
-
this.defaultConfig = this.reverseProxyConfigs.find(config => config.hostName === '*');
|
|
81
|
-
|
|
82
|
-
this.logger.info(`Router initialized with ${this.reverseProxyConfigs.length} configs (${this.getHostnames().length} unique hosts)`);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Routes a request based on hostname and path
|
|
87
|
-
* @param req The incoming HTTP request
|
|
88
|
-
* @returns The matching proxy config or undefined if no match found
|
|
89
|
-
*/
|
|
90
|
-
public routeReq(req: plugins.http.IncomingMessage): IReverseProxyConfig {
|
|
91
|
-
const result = this.routeReqWithDetails(req);
|
|
92
|
-
return result ? result.config : undefined;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Routes a request with detailed matching information
|
|
97
|
-
* @param req The incoming HTTP request
|
|
98
|
-
* @returns Detailed routing result including matched config and path information
|
|
99
|
-
*/
|
|
100
|
-
public routeReqWithDetails(req: plugins.http.IncomingMessage): RouterResult | undefined {
|
|
101
|
-
// Extract and validate host header
|
|
102
|
-
const originalHost = req.headers.host;
|
|
103
|
-
if (!originalHost) {
|
|
104
|
-
this.logger.error('No host header found in request');
|
|
105
|
-
return this.defaultConfig ? { config: this.defaultConfig } : undefined;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Parse URL for path matching
|
|
109
|
-
const parsedUrl = plugins.url.parse(req.url || '/');
|
|
110
|
-
const urlPath = parsedUrl.pathname || '/';
|
|
111
|
-
|
|
112
|
-
// Extract hostname without port
|
|
113
|
-
const hostWithoutPort = originalHost.split(':')[0].toLowerCase();
|
|
114
|
-
|
|
115
|
-
// First try exact hostname match
|
|
116
|
-
const exactConfig = this.findConfigForHost(hostWithoutPort, urlPath);
|
|
117
|
-
if (exactConfig) {
|
|
118
|
-
return exactConfig;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Try various wildcard patterns
|
|
122
|
-
if (hostWithoutPort.includes('.')) {
|
|
123
|
-
const domainParts = hostWithoutPort.split('.');
|
|
124
|
-
|
|
125
|
-
// Try wildcard subdomain (*.example.com)
|
|
126
|
-
if (domainParts.length > 2) {
|
|
127
|
-
const wildcardDomain = `*.${domainParts.slice(1).join('.')}`;
|
|
128
|
-
const wildcardConfig = this.findConfigForHost(wildcardDomain, urlPath);
|
|
129
|
-
if (wildcardConfig) {
|
|
130
|
-
return wildcardConfig;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Try TLD wildcard (example.*)
|
|
135
|
-
const baseDomain = domainParts.slice(0, -1).join('.');
|
|
136
|
-
const tldWildcardDomain = `${baseDomain}.*`;
|
|
137
|
-
const tldWildcardConfig = this.findConfigForHost(tldWildcardDomain, urlPath);
|
|
138
|
-
if (tldWildcardConfig) {
|
|
139
|
-
return tldWildcardConfig;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Try complex wildcard patterns
|
|
143
|
-
const wildcardPatterns = this.findWildcardMatches(hostWithoutPort);
|
|
144
|
-
for (const pattern of wildcardPatterns) {
|
|
145
|
-
const wildcardConfig = this.findConfigForHost(pattern, urlPath);
|
|
146
|
-
if (wildcardConfig) {
|
|
147
|
-
return wildcardConfig;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Fall back to default config if available
|
|
153
|
-
if (this.defaultConfig) {
|
|
154
|
-
this.logger.warn(`No specific config found for host: ${hostWithoutPort}, using default`);
|
|
155
|
-
return { config: this.defaultConfig };
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
this.logger.error(`No config found for host: ${hostWithoutPort}`);
|
|
159
|
-
return undefined;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Find potential wildcard patterns that could match a given hostname
|
|
164
|
-
* Handles complex patterns like "*.lossless*" or other partial matches
|
|
165
|
-
* @param hostname The hostname to find wildcard matches for
|
|
166
|
-
* @returns Array of potential wildcard patterns that could match
|
|
167
|
-
*/
|
|
168
|
-
private findWildcardMatches(hostname: string): string[] {
|
|
169
|
-
const patterns: string[] = [];
|
|
170
|
-
const hostnameParts = hostname.split('.');
|
|
171
|
-
|
|
172
|
-
// Find all configured hostnames that contain wildcards
|
|
173
|
-
const wildcardConfigs = this.reverseProxyConfigs.filter(
|
|
174
|
-
config => config.hostName.includes('*')
|
|
175
|
-
);
|
|
176
|
-
|
|
177
|
-
// Extract unique wildcard patterns
|
|
178
|
-
const wildcardPatterns = [...new Set(
|
|
179
|
-
wildcardConfigs.map(config => config.hostName.toLowerCase())
|
|
180
|
-
)];
|
|
181
|
-
|
|
182
|
-
// For each wildcard pattern, check if it could match the hostname
|
|
183
|
-
// using simplified regex pattern matching
|
|
184
|
-
for (const pattern of wildcardPatterns) {
|
|
185
|
-
// Skip the default wildcard '*'
|
|
186
|
-
if (pattern === '*') continue;
|
|
187
|
-
|
|
188
|
-
// Skip already checked patterns (*.domain.com and domain.*)
|
|
189
|
-
if (pattern.startsWith('*.') && pattern.indexOf('*', 2) === -1) continue;
|
|
190
|
-
if (pattern.endsWith('.*') && pattern.indexOf('*') === pattern.length - 1) continue;
|
|
191
|
-
|
|
192
|
-
// Convert wildcard pattern to regex
|
|
193
|
-
const regexPattern = pattern
|
|
194
|
-
.replace(/\./g, '\\.') // Escape dots
|
|
195
|
-
.replace(/\*/g, '.*'); // Convert * to .* for regex
|
|
196
|
-
|
|
197
|
-
// Create regex object with case insensitive flag
|
|
198
|
-
const regex = new RegExp(`^${regexPattern}$`, 'i');
|
|
199
|
-
|
|
200
|
-
// If hostname matches this complex pattern, add it to the list
|
|
201
|
-
if (regex.test(hostname)) {
|
|
202
|
-
patterns.push(pattern);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return patterns;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Find a config for a specific host and path
|
|
211
|
-
*/
|
|
212
|
-
private findConfigForHost(hostname: string, path: string): RouterResult | undefined {
|
|
213
|
-
// Find all configs for this hostname
|
|
214
|
-
const configs = this.reverseProxyConfigs.filter(
|
|
215
|
-
config => config.hostName.toLowerCase() === hostname.toLowerCase()
|
|
216
|
-
);
|
|
217
|
-
|
|
218
|
-
if (configs.length === 0) {
|
|
219
|
-
return undefined;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// First try configs with path patterns
|
|
223
|
-
const configsWithPaths = configs.filter(config => this.pathPatterns.has(config));
|
|
224
|
-
|
|
225
|
-
// Sort by path pattern specificity - more specific first
|
|
226
|
-
configsWithPaths.sort((a, b) => {
|
|
227
|
-
const aPattern = this.pathPatterns.get(a) || '';
|
|
228
|
-
const bPattern = this.pathPatterns.get(b) || '';
|
|
229
|
-
|
|
230
|
-
// Exact patterns come before wildcard patterns
|
|
231
|
-
const aHasWildcard = aPattern.includes('*');
|
|
232
|
-
const bHasWildcard = bPattern.includes('*');
|
|
233
|
-
|
|
234
|
-
if (aHasWildcard && !bHasWildcard) return 1;
|
|
235
|
-
if (!aHasWildcard && bHasWildcard) return -1;
|
|
236
|
-
|
|
237
|
-
// Longer patterns are considered more specific
|
|
238
|
-
return bPattern.length - aPattern.length;
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
// Check each config with path pattern
|
|
242
|
-
for (const config of configsWithPaths) {
|
|
243
|
-
const pathPattern = this.pathPatterns.get(config);
|
|
244
|
-
if (pathPattern) {
|
|
245
|
-
const pathMatch = this.matchPath(path, pathPattern);
|
|
246
|
-
if (pathMatch) {
|
|
247
|
-
return {
|
|
248
|
-
config,
|
|
249
|
-
pathMatch: pathMatch.matched,
|
|
250
|
-
pathParams: pathMatch.params,
|
|
251
|
-
pathRemainder: pathMatch.remainder
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// If no path pattern matched, use the first config without a path pattern
|
|
258
|
-
const configWithoutPath = configs.find(config => !this.pathPatterns.has(config));
|
|
259
|
-
if (configWithoutPath) {
|
|
260
|
-
return { config: configWithoutPath };
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
return undefined;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
* Matches a URL path against a pattern
|
|
268
|
-
* Supports:
|
|
269
|
-
* - Exact matches: /users/profile
|
|
270
|
-
* - Wildcards: /api/* (matches any path starting with /api/)
|
|
271
|
-
* - Path parameters: /users/:id (captures id as a parameter)
|
|
272
|
-
*
|
|
273
|
-
* @param path The URL path to match
|
|
274
|
-
* @param pattern The pattern to match against
|
|
275
|
-
* @returns Match result with params and remainder, or null if no match
|
|
276
|
-
*/
|
|
277
|
-
private matchPath(path: string, pattern: string): {
|
|
278
|
-
matched: string;
|
|
279
|
-
params: Record<string, string>;
|
|
280
|
-
remainder: string;
|
|
281
|
-
} | null {
|
|
282
|
-
// Handle exact match
|
|
283
|
-
if (path === pattern) {
|
|
284
|
-
return {
|
|
285
|
-
matched: pattern,
|
|
286
|
-
params: {},
|
|
287
|
-
remainder: ''
|
|
288
|
-
};
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
// Handle wildcard match
|
|
292
|
-
if (pattern.endsWith('/*')) {
|
|
293
|
-
const prefix = pattern.slice(0, -2);
|
|
294
|
-
if (path === prefix || path.startsWith(`${prefix}/`)) {
|
|
295
|
-
return {
|
|
296
|
-
matched: prefix,
|
|
297
|
-
params: {},
|
|
298
|
-
remainder: path.slice(prefix.length)
|
|
299
|
-
};
|
|
300
|
-
}
|
|
301
|
-
return null;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
// Handle path parameters
|
|
305
|
-
const patternParts = pattern.split('/').filter(p => p);
|
|
306
|
-
const pathParts = path.split('/').filter(p => p);
|
|
307
|
-
|
|
308
|
-
// Too few path parts to match
|
|
309
|
-
if (pathParts.length < patternParts.length) {
|
|
310
|
-
return null;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
const params: Record<string, string> = {};
|
|
314
|
-
|
|
315
|
-
// Compare each part
|
|
316
|
-
for (let i = 0; i < patternParts.length; i++) {
|
|
317
|
-
const patternPart = patternParts[i];
|
|
318
|
-
const pathPart = pathParts[i];
|
|
319
|
-
|
|
320
|
-
// Handle parameter
|
|
321
|
-
if (patternPart.startsWith(':')) {
|
|
322
|
-
const paramName = patternPart.slice(1);
|
|
323
|
-
params[paramName] = pathPart;
|
|
324
|
-
continue;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
// Handle wildcard at the end
|
|
328
|
-
if (patternPart === '*' && i === patternParts.length - 1) {
|
|
329
|
-
break;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
// Handle exact match for this part
|
|
333
|
-
if (patternPart !== pathPart) {
|
|
334
|
-
return null;
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
// Calculate the remainder - the unmatched path parts
|
|
339
|
-
const remainderParts = pathParts.slice(patternParts.length);
|
|
340
|
-
const remainder = remainderParts.length ? '/' + remainderParts.join('/') : '';
|
|
341
|
-
|
|
342
|
-
// Calculate the matched path
|
|
343
|
-
const matchedParts = patternParts.map((part, i) => {
|
|
344
|
-
return part.startsWith(':') ? pathParts[i] : part;
|
|
345
|
-
});
|
|
346
|
-
const matched = '/' + matchedParts.join('/');
|
|
347
|
-
|
|
348
|
-
return {
|
|
349
|
-
matched,
|
|
350
|
-
params,
|
|
351
|
-
remainder
|
|
352
|
-
};
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
/**
|
|
356
|
-
* Gets all currently active proxy configurations
|
|
357
|
-
* @returns Array of all active configurations
|
|
358
|
-
*/
|
|
359
|
-
public getProxyConfigs(): IReverseProxyConfig[] {
|
|
360
|
-
return [...this.reverseProxyConfigs];
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
/**
|
|
364
|
-
* Gets all hostnames that this router is configured to handle
|
|
365
|
-
* @returns Array of hostnames
|
|
366
|
-
*/
|
|
367
|
-
public getHostnames(): string[] {
|
|
368
|
-
const hostnames = new Set<string>();
|
|
369
|
-
for (const config of this.reverseProxyConfigs) {
|
|
370
|
-
if (config.hostName !== '*') {
|
|
371
|
-
hostnames.add(config.hostName.toLowerCase());
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
return Array.from(hostnames);
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
/**
|
|
378
|
-
* Adds a single new proxy configuration
|
|
379
|
-
* @param config The configuration to add
|
|
380
|
-
* @param pathPattern Optional path pattern for route matching
|
|
381
|
-
*/
|
|
382
|
-
public addProxyConfig(
|
|
383
|
-
config: IReverseProxyConfig,
|
|
384
|
-
pathPattern?: string
|
|
385
|
-
): void {
|
|
386
|
-
this.reverseProxyConfigs.push(config);
|
|
387
|
-
|
|
388
|
-
// Store path pattern if provided
|
|
389
|
-
if (pathPattern) {
|
|
390
|
-
this.pathPatterns.set(config, pathPattern);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
/**
|
|
395
|
-
* Sets a path pattern for an existing config
|
|
396
|
-
* @param config The existing configuration
|
|
397
|
-
* @param pathPattern The path pattern to set
|
|
398
|
-
* @returns Boolean indicating if the config was found and updated
|
|
399
|
-
*/
|
|
400
|
-
public setPathPattern(
|
|
401
|
-
config: IReverseProxyConfig,
|
|
402
|
-
pathPattern: string
|
|
403
|
-
): boolean {
|
|
404
|
-
const exists = this.reverseProxyConfigs.includes(config);
|
|
405
|
-
if (exists) {
|
|
406
|
-
this.pathPatterns.set(config, pathPattern);
|
|
407
|
-
return true;
|
|
408
|
-
}
|
|
409
|
-
return false;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
/**
|
|
413
|
-
* Removes a proxy configuration by hostname
|
|
414
|
-
* @param hostname The hostname to remove
|
|
415
|
-
* @returns Boolean indicating whether any configs were removed
|
|
416
|
-
*/
|
|
417
|
-
public removeProxyConfig(hostname: string): boolean {
|
|
418
|
-
const initialCount = this.reverseProxyConfigs.length;
|
|
419
|
-
|
|
420
|
-
// Find configs to remove
|
|
421
|
-
const configsToRemove = this.reverseProxyConfigs.filter(
|
|
422
|
-
config => config.hostName === hostname
|
|
423
|
-
);
|
|
424
|
-
|
|
425
|
-
// Remove them from the patterns map
|
|
426
|
-
for (const config of configsToRemove) {
|
|
427
|
-
this.pathPatterns.delete(config);
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
// Filter them out of the configs array
|
|
431
|
-
this.reverseProxyConfigs = this.reverseProxyConfigs.filter(
|
|
432
|
-
config => config.hostName !== hostname
|
|
433
|
-
);
|
|
434
|
-
|
|
435
|
-
return this.reverseProxyConfigs.length !== initialCount;
|
|
436
|
-
}
|
|
437
|
-
}
|