Compare commits

...

1 Commits

Author SHA1 Message Date
Juergen Kunz
aa6ddbc4a6 BREAKING_CHANGE(routing): refactor route configuration to support multiple targets
Some checks failed
Default (tags) / security (push) Successful in 53s
Default (tags) / test (push) Failing after 31m2s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2025-07-21 08:52:07 +00:00
51 changed files with 2916 additions and 158 deletions

View File

@@ -1,5 +1,5 @@
{
"expiryDate": "2025-10-01T02:31:27.435Z",
"issueDate": "2025-07-03T02:31:27.435Z",
"savedAt": "2025-07-03T02:31:27.435Z"
"expiryDate": "2025-10-18T13:15:48.916Z",
"issueDate": "2025-07-20T13:15:48.916Z",
"savedAt": "2025-07-20T13:15:48.916Z"
}

View File

@@ -1,5 +1,13 @@
# Changelog
## 2025-07-20 - 20.0.1 - BREAKING_CHANGE(routing)
Refactor route configuration to support multiple targets
- Changed route action configuration from single `target` to `targets` array
- Enables load balancing and failover capabilities with multiple upstream targets
- Updated all test files to use new `targets` array syntax
- Automatic certificate metadata refresh
## 2025-06-01 - 19.5.19 - fix(smartproxy)
Fix connection handling and improve route matching edge cases

View File

@@ -1,6 +1,6 @@
{
"name": "@push.rocks/smartproxy",
"version": "19.6.17",
"version": "20.0.1",
"private": false,
"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.",
"main": "dist_ts/index.js",
@@ -51,7 +51,8 @@
"assets/**/*",
"cli.js",
"npmextra.json",
"readme.md"
"readme.md",
"changelog.md"
],
"browserslist": [
"last 1 chrome versions"

2749
test-output.log Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -32,14 +32,14 @@ tap.test('PathMatcher - wildcard matching', async () => {
const result = PathMatcher.match('/api/*', '/api/users/123/profile');
expect(result.matches).toEqual(true);
expect(result.pathMatch).toEqual('/api'); // Normalized without trailing slash
expect(result.pathRemainder).toEqual('users/123/profile');
expect(result.pathRemainder).toEqual('/users/123/profile');
});
tap.test('PathMatcher - mixed parameters and wildcards', async () => {
const result = PathMatcher.match('/api/:version/*', '/api/v1/users/123');
expect(result.matches).toEqual(true);
expect(result.params).toEqual({ version: 'v1' });
expect(result.pathRemainder).toEqual('users/123');
expect(result.pathRemainder).toEqual('/users/123');
});
tap.test('PathMatcher - trailing slash normalization', async () => {

View File

@@ -58,7 +58,7 @@ tap.test('Shared Security Manager', async () => {
},
action: {
type: 'forward',
target: { host: 'target.com', port: 443 }
targets: [{ host: 'target.com', port: 443 }]
},
security: {
ipAllowList: ['10.0.0.*', '192.168.1.*'],
@@ -113,7 +113,7 @@ tap.test('Shared Security Manager', async () => {
},
action: {
type: 'forward',
target: { host: 'target.com', port: 443 }
targets: [{ host: 'target.com', port: 443 }]
},
security: {
rateLimit: {

View File

@@ -59,7 +59,7 @@ tap.test('should create ACME challenge route', async (tools) => {
},
action: {
type: 'forward' as const,
target: { host: 'localhost', port: 8080 }
targets: [{ host: 'localhost', port: 8080 }]
}
},
challengeRoute

View File

@@ -18,7 +18,7 @@ tap.test('should defer certificate provisioning until ports are ready', async (t
},
action: {
type: 'forward',
target: { host: 'localhost', port: 8181 },
targets: [{ host: 'localhost', port: 8181 }],
tls: {
mode: 'terminate',
certificate: 'auto',

View File

@@ -30,7 +30,7 @@ tap.test('should defer certificate provisioning until after ports are listening'
},
action: {
type: 'forward',
target: { host: 'localhost', port: 8181 },
targets: [{ host: 'localhost', port: 8181 }],
tls: {
mode: 'terminate',
certificate: 'auto',
@@ -126,7 +126,7 @@ tap.test('should have ACME challenge route ready before certificate provisioning
},
action: {
type: 'forward',
target: { host: 'localhost', port: 8181 },
targets: [{ host: 'localhost', port: 8181 }],
tls: {
mode: 'terminate',
certificate: 'auto'

View File

@@ -16,10 +16,10 @@ tap.test('SmartCertManager should call getCertificateForDomain with wildcard opt
},
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: 8080
},
}],
tls: {
mode: 'terminate',
certificate: 'auto',

View File

@@ -59,10 +59,10 @@ tap.test('SmartProxy should support custom certificate provision function', asyn
},
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: 8080
},
}],
tls: {
mode: 'terminate',
certificate: 'auto'
@@ -109,10 +109,10 @@ tap.test('Custom certificate provision function should be called', async () => {
},
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: 8080
},
}],
tls: {
mode: 'terminate',
certificate: 'auto'
@@ -172,10 +172,10 @@ tap.test('Should fallback to ACME when custom provision fails', async () => {
},
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: 8080
},
}],
tls: {
mode: 'terminate',
certificate: 'auto'
@@ -231,10 +231,10 @@ tap.test('Should not fallback when certProvisionFallbackToAcme is false', async
},
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: 8080
},
}],
tls: {
mode: 'terminate',
certificate: 'auto'
@@ -310,10 +310,10 @@ tap.test('Should return http01 for unknown domains', async () => {
},
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: 8080
},
}],
tls: {
mode: 'terminate',
certificate: 'auto'

View File

@@ -7,7 +7,7 @@ const testProxy = new SmartProxy({
match: { ports: 9443, domains: 'test.local' },
action: {
type: 'forward',
target: { host: 'localhost', port: 8080 },
targets: [{ host: 'localhost', port: 8080 }],
tls: {
mode: 'terminate',
certificate: 'auto',
@@ -67,7 +67,7 @@ tap.test('should handle static certificates', async () => {
match: { ports: 9444, domains: 'static.example.com' },
action: {
type: 'forward',
target: { host: 'localhost', port: 8080 },
targets: [{ host: 'localhost', port: 8080 }],
tls: {
mode: 'terminate',
certificate: {
@@ -96,7 +96,7 @@ tap.test('should handle ACME challenge routes', async () => {
match: { ports: 9445, domains: 'acme.local' },
action: {
type: 'forward',
target: { host: 'localhost', port: 8080 },
targets: [{ host: 'localhost', port: 8080 }],
tls: {
mode: 'terminate',
certificate: 'auto',
@@ -112,7 +112,7 @@ tap.test('should handle ACME challenge routes', async () => {
match: { ports: 9081, domains: 'acme.local' },
action: {
type: 'forward',
target: { host: 'localhost', port: 8080 }
targets: [{ host: 'localhost', port: 8080 }]
}
}],
acme: {
@@ -167,7 +167,7 @@ tap.test('should renew certificates', async () => {
match: { ports: 9446, domains: 'renew.local' },
action: {
type: 'forward',
target: { host: 'localhost', port: 8080 },
targets: [{ host: 'localhost', port: 8080 }],
tls: {
mode: 'terminate',
certificate: 'auto',

View File

@@ -8,7 +8,7 @@ tap.test('should create SmartProxy with certificate routes', async () => {
match: { ports: 8443, domains: 'test.example.com' },
action: {
type: 'forward',
target: { host: 'localhost', port: 8080 },
targets: [{ host: 'localhost', port: 8080 }],
tls: {
mode: 'terminate',
certificate: 'auto',

View File

@@ -13,7 +13,7 @@ tap.test('cleanup queue bug - verify queue processing handles more than batch si
match: { ports: 8588 },
action: {
type: 'forward',
target: { host: 'localhost', port: 9996 }
targets: [{ host: 'localhost', port: 9996 }]
}
}],
enableDetailedLogging: false,

View File

@@ -18,10 +18,10 @@ tap.test('should handle clients that connect and immediately disconnect without
match: { ports: 8560 },
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: 9999 // Non-existent port
}
}]
}
}]
});
@@ -173,10 +173,10 @@ tap.test('should handle clients that error during connection', async () => {
match: { ports: 8561 },
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: 9999
}
}]
}
}]
});

View File

@@ -20,10 +20,10 @@ tap.test('comprehensive connection cleanup test - all scenarios', async () => {
match: { ports: 8570 },
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: 9999 // Non-existent port
}
}]
}
},
{
@@ -31,10 +31,10 @@ tap.test('comprehensive connection cleanup test - all scenarios', async () => {
match: { ports: 8571 },
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: 9999 // Non-existent port
},
}],
tls: {
mode: 'passthrough'
}
@@ -215,10 +215,10 @@ tap.test('comprehensive connection cleanup test - all scenarios', async () => {
action: {
type: 'forward',
forwardingEngine: 'nftables',
target: {
targets: [{
host: 'localhost',
port: 9999
}
}]
}
}]
});

View File

@@ -65,10 +65,10 @@ tap.test('should forward TCP connections correctly', async () => {
},
action: {
type: 'forward',
target: {
targets: [{
host: '127.0.0.1',
port: 7001,
},
}],
},
},
],
@@ -118,10 +118,10 @@ tap.test('should handle TLS passthrough correctly', async () => {
tls: {
mode: 'passthrough',
},
target: {
targets: [{
host: '127.0.0.1',
port: 7002,
},
}],
},
},
],
@@ -179,10 +179,10 @@ tap.test('should handle SNI-based forwarding', async () => {
tls: {
mode: 'passthrough',
},
target: {
targets: [{
host: '127.0.0.1',
port: 7002,
},
}],
},
},
{
@@ -197,10 +197,10 @@ tap.test('should handle SNI-based forwarding', async () => {
tls: {
mode: 'passthrough',
},
target: {
targets: [{
host: '127.0.0.1',
port: 7002,
},
}],
},
},
],

View File

@@ -90,10 +90,10 @@ tap.test('Setup test environment', async () => {
},
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: TEST_SERVER_PORT
}
}]
},
security: {
maxConnections: 5 // Low limit for testing
@@ -198,10 +198,10 @@ tap.test('HttpProxy per-IP validation', async () => {
},
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: TEST_SERVER_PORT
},
}],
tls: {
mode: 'terminate'
}

View File

@@ -9,7 +9,7 @@ tap.test('should verify certificate manager callback is preserved on updateRoute
match: { ports: [18443], domains: ['test.local'] },
action: {
type: 'forward',
target: { host: 'localhost', port: 3000 },
targets: [{ host: 'localhost', port: 3000 }],
tls: {
mode: 'terminate',
certificate: 'auto',
@@ -63,7 +63,7 @@ tap.test('should verify certificate manager callback is preserved on updateRoute
match: { ports: [18444], domains: ['test2.local'] },
action: {
type: 'forward',
target: { host: 'localhost', port: 3001 },
targets: [{ host: 'localhost', port: 3001 }],
tls: {
mode: 'terminate',
certificate: 'auto',

View File

@@ -37,7 +37,7 @@ tap.test('regular forward route should work correctly', async () => {
match: { ports: 7890 },
action: {
type: 'forward',
target: { host: 'localhost', port: 6789 }
targets: [{ host: 'localhost', port: 6789 }]
}
}]
});
@@ -106,7 +106,7 @@ tap.skip.test('NFTables forward route should not terminate connections (requires
action: {
type: 'forward',
forwardingEngine: 'nftables',
target: { host: 'localhost', port: 6789 }
targets: [{ host: 'localhost', port: 6789 }]
}
}]
});

View File

@@ -39,10 +39,10 @@ tap.test('forward connections should not be immediately closed', async (t) => {
},
action: {
type: 'forward',
target: {
targets: [{
host: '127.0.0.1',
port: 9090,
},
}],
},
},
],

View File

@@ -39,7 +39,7 @@ tap.test('Route Helpers - Create HTTP routes', async () => {
const route = helpers.httpOnly('example.com', { host: 'localhost', port: 3000 });
expect(route.action.type).toEqual('forward');
expect(route.match.domains).toEqual('example.com');
expect(route.action.target).toEqual({ host: 'localhost', port: 3000 });
expect(route.action.targets?.[0]).toEqual({ host: 'localhost', port: 3000 });
});
tap.test('Route Helpers - Create HTTPS terminate to HTTP routes', async () => {

View File

@@ -20,7 +20,7 @@ tap.test('should forward non-TLS connections on HttpProxy ports', async (tapTest
match: { ports: testPort },
action: {
type: 'forward',
target: { host: 'localhost', port: 8181 }
targets: [{ host: 'localhost', port: 8181 }]
}
}]
};
@@ -81,7 +81,7 @@ tap.test('should use direct connection for non-HttpProxy ports', async (tapTest)
match: { ports: 8080 }, // Not in useHttpProxy
action: {
type: 'forward',
target: { host: 'localhost', port: 8181 }
targets: [{ host: 'localhost', port: 8181 }]
}
}]
};
@@ -142,7 +142,7 @@ tap.test('should handle ACME HTTP-01 challenges on port 80 with HttpProxy', asyn
},
action: {
type: 'forward',
target: { host: 'localhost', port: 8080 }
targets: [{ host: 'localhost', port: 8080 }]
}
}]
};

View File

@@ -14,7 +14,7 @@ tap.test('should detect and forward non-TLS connections on useHttpProxy ports',
match: { ports: 8080 },
action: {
type: 'forward',
target: { host: 'localhost', port: 8181 }
targets: [{ host: 'localhost', port: 8181 }]
}
}]
};
@@ -140,7 +140,7 @@ tap.test('should handle TLS connections normally', async (tapTest) => {
match: { ports: 443 },
action: {
type: 'forward',
target: { host: 'localhost', port: 8443 },
targets: [{ host: 'localhost', port: 8443 }],
tls: { mode: 'terminate' }
}
}]

View File

@@ -17,7 +17,7 @@ tap.test('should detect and forward non-TLS connections on HttpProxy ports', asy
match: { ports: 8081 },
action: {
type: 'forward',
target: { host: 'localhost', port: 8181 }
targets: [{ host: 'localhost', port: 8181 }]
}
}]
});
@@ -120,7 +120,7 @@ tap.test('should properly detect non-TLS connections on HttpProxy ports', async
},
action: {
type: 'forward',
target: { host: 'localhost', port: targetPort }
targets: [{ host: 'localhost', port: targetPort }]
}
}]
});

View File

@@ -42,7 +42,7 @@ tap.test('should forward HTTP connections on port 8080', async (tapTest) => {
},
action: {
type: 'forward',
target: { host: 'localhost', port: targetPort }
targets: [{ host: 'localhost', port: targetPort }]
}
}]
});
@@ -131,7 +131,7 @@ tap.test('should handle basic HTTP request forwarding', async (tapTest) => {
},
action: {
type: 'forward',
target: { host: 'localhost', port: targetPort }
targets: [{ host: 'localhost', port: targetPort }]
}
}]
});

View File

@@ -67,7 +67,7 @@ tap.test('should handle ACME challenges on port 8080 with improved port binding
},
action: {
type: 'forward',
target: { host: 'localhost', port: targetPort },
targets: [{ host: 'localhost', port: targetPort }],
tls: {
mode: 'terminate',
certificate: 'auto' // Use ACME for certificate
@@ -83,7 +83,7 @@ tap.test('should handle ACME challenges on port 8080 with improved port binding
},
action: {
type: 'forward',
target: { host: 'localhost', port: targetPort }
targets: [{ host: 'localhost', port: targetPort }]
}
}
],
@@ -191,7 +191,7 @@ tap.test('should handle ACME challenges on port 8080 with improved port binding
},
action: {
type: 'forward' as const,
target: { host: 'localhost', port: targetPort }
targets: [{ host: 'localhost', port: targetPort }]
}
}
];

View File

@@ -95,10 +95,10 @@ tap.test('should support static host/port routes', async () => {
},
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: serverPort
}
}]
}
}
];
@@ -135,13 +135,13 @@ tap.test('should support function-based host', async () => {
},
action: {
type: 'forward',
target: {
targets: [{
host: (context: IRouteContext) => {
// Return localhost always in this test
return 'localhost';
},
port: serverPort
}
}]
}
}
];
@@ -178,13 +178,13 @@ tap.test('should support function-based port', async () => {
},
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: (context: IRouteContext) => {
// Return test server port
return serverPort;
}
}
}]
}
}
];
@@ -221,14 +221,14 @@ tap.test('should support function-based host AND port', async () => {
},
action: {
type: 'forward',
target: {
targets: [{
host: (context: IRouteContext) => {
return 'localhost';
},
port: (context: IRouteContext) => {
return serverPort;
}
}
}]
}
}
];
@@ -265,7 +265,7 @@ tap.test('should support context-based routing with path', async () => {
},
action: {
type: 'forward',
target: {
targets: [{
host: (context: IRouteContext) => {
// Use path to determine host
if (context.path?.startsWith('/api')) {
@@ -275,7 +275,7 @@ tap.test('should support context-based routing with path', async () => {
}
},
port: serverPort
}
}]
}
}
];

View File

@@ -40,7 +40,7 @@ tap.test('keepalive support - verify keepalive connections are properly handled'
match: { ports: 8590 },
action: {
type: 'forward',
target: { host: 'localhost', port: 9998 }
targets: [{ host: 'localhost', port: 9998 }]
}
}],
keepAlive: true,
@@ -117,7 +117,7 @@ tap.test('keepalive support - verify keepalive connections are properly handled'
match: { ports: 8591 },
action: {
type: 'forward',
target: { host: 'localhost', port: 9998 }
targets: [{ host: 'localhost', port: 9998 }]
}
}],
keepAlive: true,
@@ -178,7 +178,7 @@ tap.test('keepalive support - verify keepalive connections are properly handled'
match: { ports: 8592 },
action: {
type: 'forward',
target: { host: 'localhost', port: 9998 }
targets: [{ host: 'localhost', port: 9998 }]
}
}],
keepAlive: true,

View File

@@ -39,10 +39,10 @@ tap.test('setup test environment', async () => {
},
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: 9876
}
}]
// No TLS configuration - just plain TCP forwarding
}
}],

View File

@@ -36,10 +36,10 @@ tap.test('should create SmartProxy instance with new metrics', async () => {
},
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: echoServerPort
},
}],
tls: {
mode: 'passthrough'
}

View File

@@ -34,10 +34,10 @@ tap.skip.test('NFTables forwarding should not terminate connections (requires ro
action: {
type: 'forward',
forwardingEngine: 'nftables',
target: {
targets: [{
host: '127.0.0.1',
port: 8001,
},
}],
},
},
// Also add regular forwarding route for comparison
@@ -49,10 +49,10 @@ tap.skip.test('NFTables forwarding should not terminate connections (requires ro
},
action: {
type: 'forward',
target: {
targets: [{
host: '127.0.0.1',
port: 8001,
},
}],
},
},
],

View File

@@ -42,10 +42,10 @@ const sampleRoute: IRouteConfig = {
},
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: 8000
},
}],
forwardingEngine: 'nftables',
nftables: {
protocol: 'tcp',
@@ -115,10 +115,10 @@ tap.skip.test('NFTablesManager route updating test', async () => {
...sampleRoute,
action: {
...sampleRoute.action,
target: {
targets: [{
host: 'localhost',
port: 9000 // Different port
},
}],
nftables: {
...sampleRoute.action.nftables,
protocol: 'all' // Different protocol
@@ -147,10 +147,10 @@ tap.skip.test('NFTablesManager route deprovisioning test', async () => {
...sampleRoute,
action: {
...sampleRoute.action,
target: {
targets: [{
host: 'localhost',
port: 9000 // Different port from original test
},
}],
nftables: {
...sampleRoute.action.nftables,
protocol: 'all' // Different protocol from original test

View File

@@ -91,7 +91,7 @@ testFn('SmartProxy getNfTablesStatus functionality', async () => {
match: { ports: 3004 },
action: {
type: 'forward',
target: { host: 'localhost', port: 3005 }
targets: [{ host: 'localhost', port: 3005 }]
}
}
]

View File

@@ -29,7 +29,7 @@ tap.test('port forwarding should not immediately close connections', async (tool
match: { ports: 9999 },
action: {
type: 'forward',
target: { host: 'localhost', port: 8888 }
targets: [{ host: 'localhost', port: 8888 }]
}
}]
});
@@ -63,7 +63,7 @@ tap.test('TLS passthrough should work correctly', async () => {
action: {
type: 'forward',
tls: { mode: 'passthrough' },
target: { host: 'localhost', port: 443 }
targets: [{ host: 'localhost', port: 443 }]
}
}]
});

View File

@@ -214,12 +214,12 @@ tap.test('should handle errors in port mapping functions', async () => {
},
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: () => {
throw new Error('Test error in port mapping function');
}
}
}]
},
name: 'Error Route'
};

View File

@@ -21,7 +21,7 @@ tap.test('should not double-register port 80 when user route and ACME use same p
},
action: {
type: 'forward' as const,
target: { host: 'localhost', port: 3000 }
targets: [{ host: 'localhost', port: 3000 }]
}
},
{
@@ -31,7 +31,7 @@ tap.test('should not double-register port 80 when user route and ACME use same p
},
action: {
type: 'forward' as const,
target: { host: 'localhost', port: 3001 },
targets: [{ host: 'localhost', port: 3001 }],
tls: {
mode: 'terminate' as const,
certificate: 'auto' as const
@@ -153,7 +153,7 @@ tap.test('should handle ACME on different port than user routes', async (tools)
},
action: {
type: 'forward' as const,
target: { host: 'localhost', port: 3000 }
targets: [{ host: 'localhost', port: 3000 }]
}
},
{
@@ -163,7 +163,7 @@ tap.test('should handle ACME on different port than user routes', async (tools)
},
action: {
type: 'forward' as const,
target: { host: 'localhost', port: 3001 },
targets: [{ host: 'localhost', port: 3001 }],
tls: {
mode: 'terminate' as const,
certificate: 'auto' as const

View File

@@ -15,10 +15,10 @@ tap.test('setup two smartproxies in a chain configuration', async () => {
},
action: {
type: 'forward',
target: {
targets: [{
host: 'httpbin.org',
port: 443
}
}]
}
}
],
@@ -45,10 +45,10 @@ tap.test('setup two smartproxies in a chain configuration', async () => {
},
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: 8002
},
}],
sendProxyProtocol: true
}
}

View File

@@ -32,10 +32,10 @@ tap.test('simple proxy chain test - identify connection accumulation', async ()
match: { ports: 8591 },
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: 9998 // Backend that closes immediately
}
}]
}
}]
});
@@ -50,10 +50,10 @@ tap.test('simple proxy chain test - identify connection accumulation', async ()
match: { ports: 8590 },
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: 8591 // Forward to proxy2
}
}]
}
}]
});

View File

@@ -19,10 +19,10 @@ tap.test('should handle proxy chaining without connection accumulation', async (
match: { ports: 8581 },
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: 9999 // Non-existent backend
}
}]
}
}]
});
@@ -37,10 +37,10 @@ tap.test('should handle proxy chaining without connection accumulation', async (
match: { ports: 8580 },
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: 8581 // Forward to proxy2
}
}]
}
}]
});
@@ -270,10 +270,10 @@ tap.test('should handle proxy chain with HTTP traffic', async () => {
match: { ports: 8583 },
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: 9999 // Non-existent backend
}
}]
}
}]
});
@@ -289,10 +289,10 @@ tap.test('should handle proxy chain with HTTP traffic', async () => {
match: { ports: 8582 },
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: 8583 // Forward to proxy2
}
}]
}
}]
});

View File

@@ -19,10 +19,10 @@ tap.test('should handle rapid connection retries without leaking connections', a
match: { ports: 8550 },
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: 9999 // Non-existent port to force connection failures
}
}]
}
}]
});

View File

@@ -17,7 +17,7 @@ tap.test('should set update routes callback on certificate manager', async () =>
},
action: {
type: 'forward',
target: { host: 'localhost', port: 3000 },
targets: [{ host: 'localhost', port: 3000 }],
tls: {
mode: 'terminate',
certificate: 'auto',
@@ -95,7 +95,7 @@ tap.test('should set update routes callback on certificate manager', async () =>
},
action: {
type: 'forward',
target: { host: 'localhost', port: 3001 },
targets: [{ host: 'localhost', port: 3001 }],
tls: {
mode: 'terminate',
certificate: 'auto',

View File

@@ -28,10 +28,10 @@ tap.test('route security should block connections from unauthorized IPs', async
},
action: {
type: 'forward',
target: {
targets: [{
host: '127.0.0.1',
port: 9990
}
}]
},
security: {
// Only allow a non-existent IP
@@ -142,10 +142,10 @@ tap.test('route security with block list should work', async () => {
},
action: {
type: 'forward',
target: {
targets: [{
host: '127.0.0.1',
port: 9992
}
}]
},
security: { // Security at route level, not action level
ipBlockList: ['127.0.0.1', '::1', '::ffff:127.0.0.1']
@@ -234,10 +234,10 @@ tap.test('route without security should allow all connections', async () => {
},
action: {
type: 'forward',
target: {
targets: [{
host: '127.0.0.1',
port: 9994
}
}]
}
// No security defined
}];

View File

@@ -10,10 +10,10 @@ tap.test('route security should be correctly configured', async () => {
},
action: {
type: 'forward' as const,
target: {
targets: [{
host: '127.0.0.1',
port: 8991
},
}],
security: {
ipAllowList: ['192.168.1.1'],
ipBlockList: ['10.0.0.1']

View File

@@ -26,10 +26,10 @@ tap.test('route-specific security should be enforced', async () => {
},
action: {
type: 'forward',
target: {
targets: [{
host: '127.0.0.1',
port: 8877
}
}]
},
security: {
ipAllowList: ['127.0.0.1', '::1', '::ffff:127.0.0.1']
@@ -108,10 +108,10 @@ tap.test('route-specific IP block list should be enforced', async () => {
},
action: {
type: 'forward',
target: {
targets: [{
host: '127.0.0.1',
port: 8879
}
}]
},
security: {
ipAllowList: ['0.0.0.0/0', '::/0'], // Allow all IPs
@@ -215,10 +215,10 @@ tap.test('routes without security should allow all connections', async () => {
},
action: {
type: 'forward',
target: {
targets: [{
host: '127.0.0.1',
port: 8881
}
}]
// No security section - should allow all
}
}];

View File

@@ -13,10 +13,10 @@ const createRoute = (id: number, domain: string, port: number = 8443) => ({
},
action: {
type: 'forward' as const,
target: {
targets: [{
host: 'localhost',
port: 3000 + id
},
}],
tls: {
mode: 'terminate' as const,
certificate: 'auto' as const,
@@ -209,10 +209,10 @@ tap.test('should handle route updates when cert manager is not initialized', asy
},
action: {
type: 'forward' as const,
target: {
targets: [{
host: 'localhost',
port: 3000
}
}]
}
}]
});

View File

@@ -37,10 +37,10 @@ function createRouteConfig(
},
action: {
type: 'forward',
target: {
targets: [{
host: destinationIp,
port: destinationPort
}
}]
}
};
}

View File

@@ -15,10 +15,10 @@ tap.test('should create a SmartCertManager instance', async () => {
},
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: 3000
},
}],
tls: {
mode: 'terminate',
certificate: 'auto',

View File

@@ -30,7 +30,7 @@ tap.test('stuck connection cleanup - verify connections to hanging backends are
match: { ports: 8589 },
action: {
type: 'forward',
target: { host: 'localhost', port: 9997 }
targets: [{ host: 'localhost', port: 9997 }]
}
}],
keepAlive: true,

View File

@@ -17,7 +17,7 @@ tap.test('websocket keep-alive settings for SNI passthrough', async (tools) => {
match: { ports: 8443, domains: 'test.local' },
action: {
type: 'forward',
target: { host: 'localhost', port: 9443 },
targets: [{ host: 'localhost', port: 9443 }],
tls: { mode: 'passthrough' }
}
}
@@ -108,7 +108,7 @@ tap.test('long-lived connection survival test', async (tools) => {
match: { ports: 8444 },
action: {
type: 'forward',
target: { host: 'localhost', port: 9444 }
targets: [{ host: 'localhost', port: 9444 }]
}
}
]

View File

@@ -52,10 +52,10 @@ tap.test('zombie connection cleanup - verify inactivity check detects and cleans
match: { ports: 8591 },
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: 9998
}
}]
}
}]
});
@@ -71,10 +71,10 @@ tap.test('zombie connection cleanup - verify inactivity check detects and cleans
match: { ports: 8590 },
action: {
type: 'forward',
target: {
targets: [{
host: 'localhost',
port: 8591
}
}]
}
}]
});