@push.rocks/smartproxy 19.5.18 → 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/00_commitinfo_data.js +2 -2
- 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/core/utils/socket-utils.d.ts +0 -15
- package/dist_ts/core/utils/socket-utils.js +1 -35
- package/dist_ts/forwarding/handlers/https-terminate-to-http-handler.js +47 -32
- package/dist_ts/forwarding/handlers/https-terminate-to-https-handler.js +51 -32
- 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 +210 -1
- package/readme.plan.md +621 -0
- package/readme.routing.md +341 -0
- package/ts/00_commitinfo_data.ts +1 -1
- 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/core/utils/socket-utils.ts +0 -44
- package/ts/forwarding/handlers/https-terminate-to-http-handler.ts +47 -33
- package/ts/forwarding/handlers/https-terminate-to-https-handler.ts +55 -35
- 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
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@push.rocks/smartproxy',
|
|
6
|
-
version: '19.5.
|
|
6
|
+
version: '19.5.19',
|
|
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
|
};
|
|
9
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx3QkFBd0I7SUFDOUIsT0FBTyxFQUFFLFNBQVM7SUFDbEIsV0FBVyxFQUFFLHFQQUFxUDtDQUNuUSxDQUFBIn0=
|
|
@@ -4,4 +4,6 @@
|
|
|
4
4
|
export * from './common-types.js';
|
|
5
5
|
export * from './socket-augmentation.js';
|
|
6
6
|
export * from './route-context.js';
|
|
7
|
-
|
|
7
|
+
export * from './wrapped-socket.js';
|
|
8
|
+
export * from './socket-types.js';
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9jb3JlL21vZGVscy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUVILGNBQWMsbUJBQW1CLENBQUM7QUFDbEMsY0FBYywwQkFBMEIsQ0FBQztBQUN6QyxjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyxtQkFBbUIsQ0FBQyJ9
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as net from 'net';
|
|
2
|
+
import { WrappedSocket } from './wrapped-socket.js';
|
|
3
|
+
/**
|
|
4
|
+
* Type guard to check if a socket is a WrappedSocket
|
|
5
|
+
*/
|
|
6
|
+
export declare function isWrappedSocket(socket: net.Socket | WrappedSocket): socket is WrappedSocket;
|
|
7
|
+
/**
|
|
8
|
+
* Helper to get the underlying socket from either a Socket or WrappedSocket
|
|
9
|
+
*/
|
|
10
|
+
export declare function getUnderlyingSocket(socket: net.Socket | WrappedSocket): net.Socket;
|
|
11
|
+
/**
|
|
12
|
+
* Type that represents either a regular socket or a wrapped socket
|
|
13
|
+
*/
|
|
14
|
+
export type AnySocket = net.Socket | WrappedSocket;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as net from 'net';
|
|
2
|
+
import { WrappedSocket } from './wrapped-socket.js';
|
|
3
|
+
/**
|
|
4
|
+
* Type guard to check if a socket is a WrappedSocket
|
|
5
|
+
*/
|
|
6
|
+
export function isWrappedSocket(socket) {
|
|
7
|
+
return socket instanceof WrappedSocket || 'socket' in socket;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Helper to get the underlying socket from either a Socket or WrappedSocket
|
|
11
|
+
*/
|
|
12
|
+
export function getUnderlyingSocket(socket) {
|
|
13
|
+
return isWrappedSocket(socket) ? socket.socket : socket;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29ja2V0LXR5cGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvY29yZS9tb2RlbHMvc29ja2V0LXR5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxHQUFHLE1BQU0sS0FBSyxDQUFDO0FBQzNCLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUVwRDs7R0FFRztBQUNILE1BQU0sVUFBVSxlQUFlLENBQUMsTUFBa0M7SUFDaEUsT0FBTyxNQUFNLFlBQVksYUFBYSxJQUFJLFFBQVEsSUFBSSxNQUFNLENBQUM7QUFDL0QsQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLG1CQUFtQixDQUFDLE1BQWtDO0lBQ3BFLE9BQU8sZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7QUFDMUQsQ0FBQyJ9
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
/**
|
|
3
|
+
* WrappedSocket wraps a regular net.Socket to provide transparent access
|
|
4
|
+
* to the real client IP and port when behind a proxy using PROXY protocol.
|
|
5
|
+
*
|
|
6
|
+
* This is the FOUNDATION for all PROXY protocol support and must be implemented
|
|
7
|
+
* before any protocol parsing can occur.
|
|
8
|
+
*
|
|
9
|
+
* This implementation uses a Proxy to delegate all properties and methods
|
|
10
|
+
* to the underlying socket while allowing override of specific properties.
|
|
11
|
+
*/
|
|
12
|
+
export declare class WrappedSocket {
|
|
13
|
+
readonly socket: plugins.net.Socket;
|
|
14
|
+
private realClientIP?;
|
|
15
|
+
private realClientPort?;
|
|
16
|
+
[key: string]: any;
|
|
17
|
+
constructor(socket: plugins.net.Socket, realClientIP?: string, realClientPort?: number);
|
|
18
|
+
/**
|
|
19
|
+
* Returns the real client IP if available, otherwise the socket's remote address
|
|
20
|
+
*/
|
|
21
|
+
get remoteAddress(): string | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Returns the real client port if available, otherwise the socket's remote port
|
|
24
|
+
*/
|
|
25
|
+
get remotePort(): number | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Indicates if this connection came through a trusted proxy
|
|
28
|
+
*/
|
|
29
|
+
get isFromTrustedProxy(): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Updates the real client information (called after parsing PROXY protocol)
|
|
32
|
+
*/
|
|
33
|
+
setProxyInfo(ip: string, port: number): void;
|
|
34
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
/**
|
|
3
|
+
* WrappedSocket wraps a regular net.Socket to provide transparent access
|
|
4
|
+
* to the real client IP and port when behind a proxy using PROXY protocol.
|
|
5
|
+
*
|
|
6
|
+
* This is the FOUNDATION for all PROXY protocol support and must be implemented
|
|
7
|
+
* before any protocol parsing can occur.
|
|
8
|
+
*
|
|
9
|
+
* This implementation uses a Proxy to delegate all properties and methods
|
|
10
|
+
* to the underlying socket while allowing override of specific properties.
|
|
11
|
+
*/
|
|
12
|
+
export class WrappedSocket {
|
|
13
|
+
constructor(socket, realClientIP, realClientPort) {
|
|
14
|
+
this.socket = socket;
|
|
15
|
+
this.realClientIP = realClientIP;
|
|
16
|
+
this.realClientPort = realClientPort;
|
|
17
|
+
// Create a proxy that delegates everything to the underlying socket
|
|
18
|
+
return new Proxy(this, {
|
|
19
|
+
get(target, prop, receiver) {
|
|
20
|
+
// Override specific properties
|
|
21
|
+
if (prop === 'remoteAddress') {
|
|
22
|
+
return target.remoteAddress;
|
|
23
|
+
}
|
|
24
|
+
if (prop === 'remotePort') {
|
|
25
|
+
return target.remotePort;
|
|
26
|
+
}
|
|
27
|
+
if (prop === 'socket') {
|
|
28
|
+
return target.socket;
|
|
29
|
+
}
|
|
30
|
+
if (prop === 'realClientIP') {
|
|
31
|
+
return target.realClientIP;
|
|
32
|
+
}
|
|
33
|
+
if (prop === 'realClientPort') {
|
|
34
|
+
return target.realClientPort;
|
|
35
|
+
}
|
|
36
|
+
if (prop === 'isFromTrustedProxy') {
|
|
37
|
+
return target.isFromTrustedProxy;
|
|
38
|
+
}
|
|
39
|
+
if (prop === 'setProxyInfo') {
|
|
40
|
+
return target.setProxyInfo.bind(target);
|
|
41
|
+
}
|
|
42
|
+
// For all other properties/methods, delegate to the underlying socket
|
|
43
|
+
const value = target.socket[prop];
|
|
44
|
+
if (typeof value === 'function') {
|
|
45
|
+
return value.bind(target.socket);
|
|
46
|
+
}
|
|
47
|
+
return value;
|
|
48
|
+
},
|
|
49
|
+
set(target, prop, value) {
|
|
50
|
+
// Set on the underlying socket
|
|
51
|
+
target.socket[prop] = value;
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Returns the real client IP if available, otherwise the socket's remote address
|
|
58
|
+
*/
|
|
59
|
+
get remoteAddress() {
|
|
60
|
+
return this.realClientIP || this.socket.remoteAddress;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Returns the real client port if available, otherwise the socket's remote port
|
|
64
|
+
*/
|
|
65
|
+
get remotePort() {
|
|
66
|
+
return this.realClientPort || this.socket.remotePort;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Indicates if this connection came through a trusted proxy
|
|
70
|
+
*/
|
|
71
|
+
get isFromTrustedProxy() {
|
|
72
|
+
return !!this.realClientIP;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Updates the real client information (called after parsing PROXY protocol)
|
|
76
|
+
*/
|
|
77
|
+
setProxyInfo(ip, port) {
|
|
78
|
+
this.realClientIP = ip;
|
|
79
|
+
this.realClientPort = port;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3JhcHBlZC1zb2NrZXQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9jb3JlL21vZGVscy93cmFwcGVkLXNvY2tldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGtCQUFrQixDQUFDO0FBRTVDOzs7Ozs7Ozs7R0FTRztBQUNILE1BQU0sT0FBTyxhQUFhO0lBUXhCLFlBQ0UsTUFBMEIsRUFDMUIsWUFBcUIsRUFDckIsY0FBdUI7UUFFdkIsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDckIsSUFBSSxDQUFDLFlBQVksR0FBRyxZQUFZLENBQUM7UUFDakMsSUFBSSxDQUFDLGNBQWMsR0FBRyxjQUFjLENBQUM7UUFFckMsb0VBQW9FO1FBQ3BFLE9BQU8sSUFBSSxLQUFLLENBQUMsSUFBSSxFQUFFO1lBQ3JCLEdBQUcsQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLFFBQVE7Z0JBQ3hCLCtCQUErQjtnQkFDL0IsSUFBSSxJQUFJLEtBQUssZUFBZSxFQUFFLENBQUM7b0JBQzdCLE9BQU8sTUFBTSxDQUFDLGFBQWEsQ0FBQztnQkFDOUIsQ0FBQztnQkFDRCxJQUFJLElBQUksS0FBSyxZQUFZLEVBQUUsQ0FBQztvQkFDMUIsT0FBTyxNQUFNLENBQUMsVUFBVSxDQUFDO2dCQUMzQixDQUFDO2dCQUNELElBQUksSUFBSSxLQUFLLFFBQVEsRUFBRSxDQUFDO29CQUN0QixPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUM7Z0JBQ3ZCLENBQUM7Z0JBQ0QsSUFBSSxJQUFJLEtBQUssY0FBYyxFQUFFLENBQUM7b0JBQzVCLE9BQU8sTUFBTSxDQUFDLFlBQVksQ0FBQztnQkFDN0IsQ0FBQztnQkFDRCxJQUFJLElBQUksS0FBSyxnQkFBZ0IsRUFBRSxDQUFDO29CQUM5QixPQUFPLE1BQU0sQ0FBQyxjQUFjLENBQUM7Z0JBQy9CLENBQUM7Z0JBQ0QsSUFBSSxJQUFJLEtBQUssb0JBQW9CLEVBQUUsQ0FBQztvQkFDbEMsT0FBTyxNQUFNLENBQUMsa0JBQWtCLENBQUM7Z0JBQ25DLENBQUM7Z0JBQ0QsSUFBSSxJQUFJLEtBQUssY0FBYyxFQUFFLENBQUM7b0JBQzVCLE9BQU8sTUFBTSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQzFDLENBQUM7Z0JBRUQsc0VBQXNFO2dCQUN0RSxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQWdDLENBQUMsQ0FBQztnQkFDOUQsSUFBSSxPQUFPLEtBQUssS0FBSyxVQUFVLEVBQUUsQ0FBQztvQkFDaEMsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFDbkMsQ0FBQztnQkFDRCxPQUFPLEtBQUssQ0FBQztZQUNmLENBQUM7WUFDRCxHQUFHLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxLQUFLO2dCQUNyQiwrQkFBK0I7Z0JBQzlCLE1BQU0sQ0FBQyxNQUFjLENBQUMsSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDO2dCQUNyQyxPQUFPLElBQUksQ0FBQztZQUNkLENBQUM7U0FDRixDQUFRLENBQUM7SUFDWixDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUFJLGFBQWE7UUFDZixPQUFPLElBQUksQ0FBQyxZQUFZLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUM7SUFDeEQsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBSSxVQUFVO1FBQ1osT0FBTyxJQUFJLENBQUMsY0FBYyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDO0lBQ3ZELENBQUM7SUFFRDs7T0FFRztJQUNILElBQUksa0JBQWtCO1FBQ3BCLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUM7SUFDN0IsQ0FBQztJQUVEOztPQUVHO0lBQ0gsWUFBWSxDQUFDLEVBQVUsRUFBRSxJQUFZO1FBQ25DLElBQUksQ0FBQyxZQUFZLEdBQUcsRUFBRSxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDO0lBQzdCLENBQUM7Q0FDRiJ9
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified routing module
|
|
3
|
+
* Provides all routing functionality in a centralized location
|
|
4
|
+
*/
|
|
5
|
+
export * from './types.js';
|
|
6
|
+
export * from './matchers/index.js';
|
|
7
|
+
export * from './specificity.js';
|
|
8
|
+
export * from './route-manager.js';
|
|
9
|
+
export * from './route-utils.js';
|
|
10
|
+
export { matchers } from './matchers/index.js';
|
|
11
|
+
export { RouteSpecificity } from './specificity.js';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified routing module
|
|
3
|
+
* Provides all routing functionality in a centralized location
|
|
4
|
+
*/
|
|
5
|
+
// Export all types
|
|
6
|
+
export * from './types.js';
|
|
7
|
+
// Export all matchers
|
|
8
|
+
export * from './matchers/index.js';
|
|
9
|
+
// Export specificity calculator
|
|
10
|
+
export * from './specificity.js';
|
|
11
|
+
// Export route management
|
|
12
|
+
export * from './route-manager.js';
|
|
13
|
+
export * from './route-utils.js';
|
|
14
|
+
// Convenience re-exports
|
|
15
|
+
export { matchers } from './matchers/index.js';
|
|
16
|
+
export { RouteSpecificity } from './specificity.js';
|
|
17
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9jb3JlL3JvdXRpbmcvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBRUgsbUJBQW1CO0FBQ25CLGNBQWMsWUFBWSxDQUFDO0FBRTNCLHNCQUFzQjtBQUN0QixjQUFjLHFCQUFxQixDQUFDO0FBRXBDLGdDQUFnQztBQUNoQyxjQUFjLGtCQUFrQixDQUFDO0FBRWpDLDBCQUEwQjtBQUMxQixjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMsa0JBQWtCLENBQUM7QUFFakMseUJBQXlCO0FBQ3pCLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQyJ9
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { IMatcher, IDomainMatchOptions } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* DomainMatcher provides comprehensive domain matching functionality
|
|
4
|
+
* Supporting exact matches, wildcards, and case-insensitive matching
|
|
5
|
+
*/
|
|
6
|
+
export declare class DomainMatcher implements IMatcher<boolean, IDomainMatchOptions> {
|
|
7
|
+
private static wildcardToRegex;
|
|
8
|
+
/**
|
|
9
|
+
* Match a domain pattern against a hostname
|
|
10
|
+
* @param pattern The pattern to match (supports wildcards like *.example.com)
|
|
11
|
+
* @param hostname The hostname to test
|
|
12
|
+
* @param options Matching options
|
|
13
|
+
* @returns true if the hostname matches the pattern
|
|
14
|
+
*/
|
|
15
|
+
static match(pattern: string, hostname: string, options?: IDomainMatchOptions): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Check if a pattern contains wildcards
|
|
18
|
+
*/
|
|
19
|
+
static isWildcardPattern(pattern: string): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Calculate the specificity of a domain pattern
|
|
22
|
+
* Higher values mean more specific patterns
|
|
23
|
+
*/
|
|
24
|
+
static calculateSpecificity(pattern: string): number;
|
|
25
|
+
/**
|
|
26
|
+
* Find all matching patterns from a list
|
|
27
|
+
* Returns patterns sorted by specificity (most specific first)
|
|
28
|
+
*/
|
|
29
|
+
static findAllMatches(patterns: string[], hostname: string, options?: IDomainMatchOptions): string[];
|
|
30
|
+
/**
|
|
31
|
+
* Instance method for interface compliance
|
|
32
|
+
*/
|
|
33
|
+
match(pattern: string, hostname: string, options?: IDomainMatchOptions): boolean;
|
|
34
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DomainMatcher provides comprehensive domain matching functionality
|
|
3
|
+
* Supporting exact matches, wildcards, and case-insensitive matching
|
|
4
|
+
*/
|
|
5
|
+
export class DomainMatcher {
|
|
6
|
+
static wildcardToRegex(pattern) {
|
|
7
|
+
// Escape special regex characters except *
|
|
8
|
+
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
|
|
9
|
+
// Replace * with regex equivalent
|
|
10
|
+
const regexPattern = escaped.replace(/\*/g, '.*');
|
|
11
|
+
return new RegExp(`^${regexPattern}$`, 'i');
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Match a domain pattern against a hostname
|
|
15
|
+
* @param pattern The pattern to match (supports wildcards like *.example.com)
|
|
16
|
+
* @param hostname The hostname to test
|
|
17
|
+
* @param options Matching options
|
|
18
|
+
* @returns true if the hostname matches the pattern
|
|
19
|
+
*/
|
|
20
|
+
static match(pattern, hostname, options = {}) {
|
|
21
|
+
// Handle null/undefined cases
|
|
22
|
+
if (!pattern || !hostname) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
// Normalize inputs
|
|
26
|
+
const normalizedPattern = pattern.toLowerCase().trim();
|
|
27
|
+
const normalizedHostname = hostname.toLowerCase().trim();
|
|
28
|
+
// Remove trailing dots (FQDN normalization)
|
|
29
|
+
const cleanPattern = normalizedPattern.replace(/\.$/, '');
|
|
30
|
+
const cleanHostname = normalizedHostname.replace(/\.$/, '');
|
|
31
|
+
// Exact match (most common case)
|
|
32
|
+
if (cleanPattern === cleanHostname) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
// Wildcard matching
|
|
36
|
+
if (options.allowWildcards !== false && cleanPattern.includes('*')) {
|
|
37
|
+
const regex = this.wildcardToRegex(cleanPattern);
|
|
38
|
+
return regex.test(cleanHostname);
|
|
39
|
+
}
|
|
40
|
+
// No match
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Check if a pattern contains wildcards
|
|
45
|
+
*/
|
|
46
|
+
static isWildcardPattern(pattern) {
|
|
47
|
+
return pattern.includes('*');
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Calculate the specificity of a domain pattern
|
|
51
|
+
* Higher values mean more specific patterns
|
|
52
|
+
*/
|
|
53
|
+
static calculateSpecificity(pattern) {
|
|
54
|
+
if (!pattern)
|
|
55
|
+
return 0;
|
|
56
|
+
let score = 0;
|
|
57
|
+
// Exact domains are most specific
|
|
58
|
+
if (!pattern.includes('*')) {
|
|
59
|
+
score += 100;
|
|
60
|
+
}
|
|
61
|
+
// Count domain segments
|
|
62
|
+
const segments = pattern.split('.');
|
|
63
|
+
score += segments.length * 10;
|
|
64
|
+
// Penalize wildcards based on position
|
|
65
|
+
if (pattern.startsWith('*')) {
|
|
66
|
+
score -= 50; // Leading wildcard is very generic
|
|
67
|
+
}
|
|
68
|
+
else if (pattern.includes('*')) {
|
|
69
|
+
score -= 20; // Wildcard elsewhere is less generic
|
|
70
|
+
}
|
|
71
|
+
// Bonus for longer patterns
|
|
72
|
+
score += pattern.length;
|
|
73
|
+
return score;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Find all matching patterns from a list
|
|
77
|
+
* Returns patterns sorted by specificity (most specific first)
|
|
78
|
+
*/
|
|
79
|
+
static findAllMatches(patterns, hostname, options = {}) {
|
|
80
|
+
const matches = patterns.filter(pattern => this.match(pattern, hostname, options));
|
|
81
|
+
// Sort by specificity (highest first)
|
|
82
|
+
return matches.sort((a, b) => this.calculateSpecificity(b) - this.calculateSpecificity(a));
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Instance method for interface compliance
|
|
86
|
+
*/
|
|
87
|
+
match(pattern, hostname, options) {
|
|
88
|
+
return DomainMatcher.match(pattern, hostname, options);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG9tYWluLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdHMvY29yZS9yb3V0aW5nL21hdGNoZXJzL2RvbWFpbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQTs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sYUFBYTtJQUNoQixNQUFNLENBQUMsZUFBZSxDQUFDLE9BQWU7UUFDNUMsMkNBQTJDO1FBQzNDLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsb0JBQW9CLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDOUQsa0NBQWtDO1FBQ2xDLE1BQU0sWUFBWSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ2xELE9BQU8sSUFBSSxNQUFNLENBQUMsSUFBSSxZQUFZLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUM5QyxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsTUFBTSxDQUFDLEtBQUssQ0FDVixPQUFlLEVBQ2YsUUFBZ0IsRUFDaEIsVUFBK0IsRUFBRTtRQUVqQyw4QkFBOEI7UUFDOUIsSUFBSSxDQUFDLE9BQU8sSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQzFCLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztRQUVELG1CQUFtQjtRQUNuQixNQUFNLGlCQUFpQixHQUFHLE9BQU8sQ0FBQyxXQUFXLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUN2RCxNQUFNLGtCQUFrQixHQUFHLFFBQVEsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUV6RCw0Q0FBNEM7UUFDNUMsTUFBTSxZQUFZLEdBQUcsaUJBQWlCLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUMxRCxNQUFNLGFBQWEsR0FBRyxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRTVELGlDQUFpQztRQUNqQyxJQUFJ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
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { IMatcher, IHeaderMatchOptions } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* HeaderMatcher provides HTTP header matching functionality
|
|
4
|
+
* Supporting exact matches, patterns, and case-insensitive matching
|
|
5
|
+
*/
|
|
6
|
+
export declare class HeaderMatcher implements IMatcher<boolean, IHeaderMatchOptions> {
|
|
7
|
+
/**
|
|
8
|
+
* Match a header value against a pattern
|
|
9
|
+
* @param pattern The pattern to match
|
|
10
|
+
* @param value The header value to test
|
|
11
|
+
* @param options Matching options
|
|
12
|
+
* @returns true if the value matches the pattern
|
|
13
|
+
*/
|
|
14
|
+
static match(pattern: string, value: string | undefined, options?: IHeaderMatchOptions): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Match multiple headers against a set of required headers
|
|
17
|
+
* @param requiredHeaders Headers that must match
|
|
18
|
+
* @param actualHeaders Actual request headers
|
|
19
|
+
* @param options Matching options
|
|
20
|
+
* @returns true if all required headers match
|
|
21
|
+
*/
|
|
22
|
+
static matchAll(requiredHeaders: Record<string, string>, actualHeaders: Record<string, string | string[] | undefined>, options?: IHeaderMatchOptions): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Calculate the specificity of header requirements
|
|
25
|
+
* More headers = more specific
|
|
26
|
+
*/
|
|
27
|
+
static calculateSpecificity(headers: Record<string, string>): number;
|
|
28
|
+
/**
|
|
29
|
+
* Instance method for interface compliance
|
|
30
|
+
*/
|
|
31
|
+
match(pattern: string, value: string, options?: IHeaderMatchOptions): boolean;
|
|
32
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HeaderMatcher provides HTTP header matching functionality
|
|
3
|
+
* Supporting exact matches, patterns, and case-insensitive matching
|
|
4
|
+
*/
|
|
5
|
+
export class HeaderMatcher {
|
|
6
|
+
/**
|
|
7
|
+
* Match a header value against a pattern
|
|
8
|
+
* @param pattern The pattern to match
|
|
9
|
+
* @param value The header value to test
|
|
10
|
+
* @param options Matching options
|
|
11
|
+
* @returns true if the value matches the pattern
|
|
12
|
+
*/
|
|
13
|
+
static match(pattern, value, options = {}) {
|
|
14
|
+
// Handle missing header
|
|
15
|
+
if (value === undefined || value === null) {
|
|
16
|
+
return pattern === '' || pattern === null || pattern === undefined;
|
|
17
|
+
}
|
|
18
|
+
// Convert to string and normalize
|
|
19
|
+
const normalizedPattern = String(pattern);
|
|
20
|
+
const normalizedValue = String(value);
|
|
21
|
+
// Apply case sensitivity
|
|
22
|
+
const comparePattern = options.caseInsensitive !== false
|
|
23
|
+
? normalizedPattern.toLowerCase()
|
|
24
|
+
: normalizedPattern;
|
|
25
|
+
const compareValue = options.caseInsensitive !== false
|
|
26
|
+
? normalizedValue.toLowerCase()
|
|
27
|
+
: normalizedValue;
|
|
28
|
+
// Exact match
|
|
29
|
+
if (options.exactMatch !== false) {
|
|
30
|
+
return comparePattern === compareValue;
|
|
31
|
+
}
|
|
32
|
+
// Pattern matching (simple wildcard support)
|
|
33
|
+
if (comparePattern.includes('*')) {
|
|
34
|
+
const regex = new RegExp('^' + comparePattern.replace(/\*/g, '.*') + '$', options.caseInsensitive !== false ? 'i' : '');
|
|
35
|
+
return regex.test(normalizedValue);
|
|
36
|
+
}
|
|
37
|
+
// Contains match (if not exact match mode)
|
|
38
|
+
return compareValue.includes(comparePattern);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Match multiple headers against a set of required headers
|
|
42
|
+
* @param requiredHeaders Headers that must match
|
|
43
|
+
* @param actualHeaders Actual request headers
|
|
44
|
+
* @param options Matching options
|
|
45
|
+
* @returns true if all required headers match
|
|
46
|
+
*/
|
|
47
|
+
static matchAll(requiredHeaders, actualHeaders, options = {}) {
|
|
48
|
+
for (const [name, pattern] of Object.entries(requiredHeaders)) {
|
|
49
|
+
const headerName = options.caseInsensitive !== false
|
|
50
|
+
? name.toLowerCase()
|
|
51
|
+
: name;
|
|
52
|
+
// Find the actual header (case-insensitive search if needed)
|
|
53
|
+
let actualValue;
|
|
54
|
+
if (options.caseInsensitive !== false) {
|
|
55
|
+
const actualKey = Object.keys(actualHeaders).find(key => key.toLowerCase() === headerName);
|
|
56
|
+
const rawValue = actualKey ? actualHeaders[actualKey] : undefined;
|
|
57
|
+
// Handle array values (multiple headers with same name)
|
|
58
|
+
actualValue = Array.isArray(rawValue) ? rawValue.join(', ') : rawValue;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
const rawValue = actualHeaders[name];
|
|
62
|
+
// Handle array values (multiple headers with same name)
|
|
63
|
+
actualValue = Array.isArray(rawValue) ? rawValue.join(', ') : rawValue;
|
|
64
|
+
}
|
|
65
|
+
// Check if this header matches
|
|
66
|
+
if (!this.match(pattern, actualValue, options)) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Calculate the specificity of header requirements
|
|
74
|
+
* More headers = more specific
|
|
75
|
+
*/
|
|
76
|
+
static calculateSpecificity(headers) {
|
|
77
|
+
const count = Object.keys(headers).length;
|
|
78
|
+
let score = count * 10;
|
|
79
|
+
// Bonus for headers without wildcards (more specific)
|
|
80
|
+
for (const value of Object.values(headers)) {
|
|
81
|
+
if (!value.includes('*')) {
|
|
82
|
+
score += 5;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return score;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Instance method for interface compliance
|
|
89
|
+
*/
|
|
90
|
+
match(pattern, value, options) {
|
|
91
|
+
return HeaderMatcher.match(pattern, value, options);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVhZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdHMvY29yZS9yb3V0aW5nL21hdGNoZXJzL2hlYWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQTs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sYUFBYTtJQUN4Qjs7Ozs7O09BTUc7SUFDSCxNQUFNLENBQUMsS0FBSyxDQUNWLE9BQWUsRUFDZixLQUF5QixFQUN6QixVQUErQixFQUFFO1FBRWpDLHdCQUF3QjtRQUN4QixJQUFJLEtBQUssS0FBSyxTQUFTLElBQUksS0FBSyxLQUFLLElBQUksRUFBRSxDQUFDO1lBQzFDLE9BQU8sT0FBTyxLQUFLLEVBQUUsSUFBSSxPQUFPLEtBQUssSUFBSSxJQUFJLE9BQU8sS0FBSyxTQUFTLENBQUM7UUFDckUsQ0FBQztRQUVELGtDQUFrQztRQUNsQyxNQUFNLGlCQUFpQixHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMxQyxNQUFNLGVBQWUsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFdEMseUJBQXlCO1FBQ3pCLE1BQU0sY0FBYyxHQUFHLE9BQU8sQ0FBQyxlQUFlLEtBQUssS0FBSztZQUN0RCxDQUFDLENBQUMsaUJBQWlCLENBQUMsV0FBVyxFQUFFO1lBQ2pDLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQztRQUN0QixNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsZUFBZSxLQUFLLEtBQUs7WUFDcEQsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxXQUFXLEVBQUU7WUFDL0IsQ0FBQyxDQUFDLGVBQWUsQ0FBQztRQUVwQixjQUFjO1FBQ2QsSUFBSSxPQUFPLENBQUMsVUFBVSxLQUFLLEtBQUssRUFBRSxDQUFDO1lBQ2pDLE9BQU8sY0FBYyxLQUFLLFlBQVksQ0FBQztRQUN6QyxDQUFDO1FBRUQsNkNBQTZDO1FBQzdDLElBQUksY0FBYyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ2pDLE1BQU0s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
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified matching utilities for the routing system
|
|
3
|
+
* All route matching logic should use these matchers for consistency
|
|
4
|
+
*/
|
|
5
|
+
export * from './domain.js';
|
|
6
|
+
export * from './path.js';
|
|
7
|
+
export * from './ip.js';
|
|
8
|
+
export * from './header.js';
|
|
9
|
+
import { DomainMatcher } from './domain.js';
|
|
10
|
+
import { PathMatcher } from './path.js';
|
|
11
|
+
import { IpMatcher } from './ip.js';
|
|
12
|
+
import { HeaderMatcher } from './header.js';
|
|
13
|
+
export declare const matchers: {
|
|
14
|
+
readonly domain: typeof DomainMatcher;
|
|
15
|
+
readonly path: typeof PathMatcher;
|
|
16
|
+
readonly ip: typeof IpMatcher;
|
|
17
|
+
readonly header: typeof HeaderMatcher;
|
|
18
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified matching utilities for the routing system
|
|
3
|
+
* All route matching logic should use these matchers for consistency
|
|
4
|
+
*/
|
|
5
|
+
export * from './domain.js';
|
|
6
|
+
export * from './path.js';
|
|
7
|
+
export * from './ip.js';
|
|
8
|
+
export * from './header.js';
|
|
9
|
+
// Re-export for convenience
|
|
10
|
+
import { DomainMatcher } from './domain.js';
|
|
11
|
+
import { PathMatcher } from './path.js';
|
|
12
|
+
import { IpMatcher } from './ip.js';
|
|
13
|
+
import { HeaderMatcher } from './header.js';
|
|
14
|
+
export const matchers = {
|
|
15
|
+
domain: DomainMatcher,
|
|
16
|
+
path: PathMatcher,
|
|
17
|
+
ip: IpMatcher,
|
|
18
|
+
header: HeaderMatcher
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9jb3JlL3JvdXRpbmcvbWF0Y2hlcnMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBRUgsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxXQUFXLENBQUM7QUFDMUIsY0FBYyxTQUFTLENBQUM7QUFDeEIsY0FBYyxhQUFhLENBQUM7QUFFNUIsNEJBQTRCO0FBQzVCLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDNUMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUN4QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFNUMsTUFBTSxDQUFDLE1BQU0sUUFBUSxHQUFHO0lBQ3RCLE1BQU0sRUFBRSxhQUFhO0lBQ3JCLElBQUksRUFBRSxXQUFXO0lBQ2pCLEVBQUUsRUFBRSxTQUFTO0lBQ2IsTUFBTSxFQUFFLGFBQWE7Q0FDYixDQUFDIn0=
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { IMatcher, IIpMatchOptions } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* IpMatcher provides comprehensive IP address matching functionality
|
|
4
|
+
* Supporting exact matches, CIDR notation, ranges, and wildcards
|
|
5
|
+
*/
|
|
6
|
+
export declare class IpMatcher implements IMatcher<boolean, IIpMatchOptions> {
|
|
7
|
+
/**
|
|
8
|
+
* Check if a value is a valid IPv4 address
|
|
9
|
+
*/
|
|
10
|
+
static isValidIpv4(ip: string): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Check if a value is a valid IPv6 address (simplified check)
|
|
13
|
+
*/
|
|
14
|
+
static isValidIpv6(ip: string): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Convert IP address to numeric value for comparison
|
|
17
|
+
*/
|
|
18
|
+
private static ipToNumber;
|
|
19
|
+
/**
|
|
20
|
+
* Match an IP against a CIDR notation pattern
|
|
21
|
+
*/
|
|
22
|
+
static matchCidr(cidr: string, ip: string): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Match an IP against a wildcard pattern
|
|
25
|
+
*/
|
|
26
|
+
static matchWildcard(pattern: string, ip: string): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Match an IP against a range (e.g., "192.168.1.1-192.168.1.100")
|
|
29
|
+
*/
|
|
30
|
+
static matchRange(range: string, ip: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Match an IP pattern against an IP address
|
|
33
|
+
* Supports multiple formats:
|
|
34
|
+
* - Exact match: "192.168.1.1"
|
|
35
|
+
* - CIDR: "192.168.1.0/24"
|
|
36
|
+
* - Wildcard: "192.168.1.*"
|
|
37
|
+
* - Range: "192.168.1.1-192.168.1.100"
|
|
38
|
+
*/
|
|
39
|
+
static match(pattern: string, ip: string, options?: IIpMatchOptions): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Check if an IP is authorized based on allow and block lists
|
|
42
|
+
*/
|
|
43
|
+
static isAuthorized(ip: string, allowList?: string[], blockList?: string[]): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Calculate the specificity of an IP pattern
|
|
46
|
+
* Higher values mean more specific patterns
|
|
47
|
+
*/
|
|
48
|
+
static calculateSpecificity(pattern: string): number;
|
|
49
|
+
/**
|
|
50
|
+
* Instance method for interface compliance
|
|
51
|
+
*/
|
|
52
|
+
match(pattern: string, ip: string, options?: IIpMatchOptions): boolean;
|
|
53
|
+
}
|