This commit is contained in:
Philipp Kunz 2025-05-29 12:54:31 +00:00
parent ab1ea95070
commit 30ff3b7d8a
7 changed files with 36 additions and 180 deletions

View File

@ -1,5 +1,5 @@
{
"expiryDate": "2025-08-27T10:55:18.793Z",
"issueDate": "2025-05-29T10:55:18.793Z",
"savedAt": "2025-05-29T10:55:18.795Z"
"expiryDate": "2025-08-27T12:49:18.738Z",
"issueDate": "2025-05-29T12:49:18.738Z",
"savedAt": "2025-05-29T12:49:18.740Z"
}

View File

@ -19,7 +19,7 @@ tap.test('should defer certificate provisioning until after ports are listening'
// Create proxy with ACME certificate requirement
const proxy = new SmartProxy({
useHttpProxy: [acmePort],
httpProxyPort: 8844,
httpProxyPort: 8845, // Use different port to avoid conflicts
acme: {
email: 'test@test.local',
useProduction: false,
@ -56,21 +56,12 @@ tap.test('should defer certificate provisioning until after ports are listening'
return result;
};
// Track certificate provisioning
const originalProvisionAll = proxy['certManager'] ?
proxy['certManager']['provisionAllCertificates'] : null;
// Track that we created a certificate manager and SmartProxy will call provisionAllCertificates
let certManagerCreated = false;
if (proxy['certManager']) {
proxy['certManager']['provisionAllCertificates'] = async function() {
operationLog.push('Starting certificate provisioning');
// Check if port 80 is listening
if (!port80Listening) {
operationLog.push('ERROR: Certificate provisioning started before ports ready');
}
// Don't actually provision certificates in the test
operationLog.push('Certificate provisioning completed');
};
}
// Override createCertificateManager to set up our tracking
const originalCreateCertManager = (proxy as any).createCertificateManager;
(proxy as any).certManagerCreated = false;
// Mock certificate manager to avoid real ACME initialization
(proxy as any).createCertificateManager = async function() {
@ -81,17 +72,21 @@ tap.test('should defer certificate provisioning until after ports are listening'
setGlobalAcmeDefaults: () => {},
setAcmeStateManager: () => {},
initialize: async () => {
operationLog.push('Certificate manager initialized');
},
provisionAllCertificates: async () => {
operationLog.push('Starting certificate provisioning');
if (!port80Listening) {
operationLog.push('ERROR: Certificate provisioning started before ports ready');
}
operationLog.push('Certificate provisioning completed');
},
provisionAllCertificates: async () => {},
stop: async () => {},
getAcmeOptions: () => ({ email: 'test@test.local', useProduction: false }),
getState: () => ({ challengeRouteActive: false })
};
certManagerCreated = true;
(proxy as any).certManager = mockCertManager;
return mockCertManager;
};
@ -120,7 +115,7 @@ tap.test('should have ACME challenge route ready before certificate provisioning
const proxy = new SmartProxy({
useHttpProxy: [8080],
httpProxyPort: 8844,
httpProxyPort: 8846, // Use different port to avoid conflicts
acme: {
email: 'test@test.local',
useProduction: false,

View File

@ -1,87 +0,0 @@
import { tap, expect } from '@git.zone/tstest/tapbundle';
import { SmartProxy } from '../ts/index.js';
import * as net from 'net';
tap.test('basic forward action should work correctly', async (t) => {
t.timeout(10000);
// Create a simple echo server as the target
const targetServer = net.createServer((socket) => {
console.log('Target server: Client connected');
socket.write('Hello from target server\n');
socket.on('data', (data) => {
console.log(`Target server received: ${data.toString().trim()}`);
socket.write(`Echo: ${data}`);
});
socket.on('error', (err) => {
console.error('Target server socket error:', err);
});
});
await new Promise<void>((resolve) => {
targetServer.listen(7777, '127.0.0.1', () => {
console.log('Target server listening on port 7777');
resolve();
});
});
// Create SmartProxy with forward route
const proxy = new SmartProxy({
enableDetailedLogging: true,
routes: [{
name: 'test-forward',
match: { ports: 7778 },
action: {
type: 'forward',
target: { host: '127.0.0.1', port: 7777 }
}
}]
});
await proxy.start();
console.log('Proxy started on port 7778');
// Test the connection
const client = new net.Socket();
await new Promise<void>((resolve, reject) => {
let received = '';
let testMessageSent = false;
client.on('data', (data) => {
received += data.toString();
console.log('Client received:', data.toString().trim());
if (received.includes('Hello from target server') && !testMessageSent) {
// Send test data only once
testMessageSent = true;
client.write('Test message\n');
} else if (received.includes('Echo: Test message')) {
// Test successful
client.end();
resolve();
}
});
client.on('error', reject);
client.connect(7778, '127.0.0.1', () => {
console.log('Client connected to proxy');
});
// Add timeout
setTimeout(() => {
reject(new Error('Test timeout - no response received'));
}, 5000);
});
await proxy.stop();
targetServer.close();
console.log('Test completed successfully');
});
tap.start();

View File

@ -97,7 +97,7 @@ tap.test('regular forward route should work correctly', async () => {
await smartProxy.stop();
});
tap.skip('NFTables forward route should not terminate connections (requires root)', async () => {
tap.skip.test('NFTables forward route should not terminate connections (requires root)', async () => {
smartProxy = new SmartProxy({
routes: [{
id: 'nftables-test',

View File

@ -40,7 +40,8 @@ tap.test('should detect and forward non-TLS connections on useHttpProxy ports',
isTLS: false
}),
initiateCleanupOnce: () => {},
cleanupConnection: () => {}
cleanupConnection: () => {},
getConnectionCount: () => 1
};
// Mock route manager that returns a matching route
@ -127,7 +128,8 @@ tap.test('should handle TLS connections normally', async (tapTest) => {
tlsHandshakeComplete: false
}),
initiateCleanupOnce: () => {},
cleanupConnection: () => {}
cleanupConnection: () => {},
getConnectionCount: () => 1
};
const mockTlsManager = {

View File

@ -10,11 +10,11 @@ tap.test('should detect and forward non-TLS connections on HttpProxy ports', asy
// Create a SmartProxy instance first
const proxy = new SmartProxy({
useHttpProxy: [8080],
httpProxyPort: 8844,
useHttpProxy: [8081], // Use different port to avoid conflicts
httpProxyPort: 8847, // Use different port to avoid conflicts
routes: [{
name: 'test-http-forward',
match: { ports: 8080 },
match: { ports: 8081 },
action: {
type: 'forward',
target: { host: 'localhost', port: 8181 }
@ -47,8 +47,8 @@ tap.test('should detect and forward non-TLS connections on HttpProxy ports', asy
const client = new net.Socket();
await new Promise<void>((resolve, reject) => {
client.connect(8080, 'localhost', () => {
console.log('Client connected to proxy on port 8080');
client.connect(8081, 'localhost', () => {
console.log('Client connected to proxy on port 8081');
// Send a non-TLS HTTP request
client.write('GET / HTTP/1.1\r\nHost: test.local\r\n\r\n');
resolve();
@ -67,7 +67,9 @@ tap.test('should detect and forward non-TLS connections on HttpProxy ports', asy
client.destroy();
await proxy.stop();
// Restore original method
// Wait a bit to ensure port is released
await new Promise(resolve => setTimeout(resolve, 100));
// Restore original method
(proxy as any).httpProxyBridge.forwardToHttpProxy = originalForward;
});
@ -94,12 +96,12 @@ tap.test('should properly detect non-TLS connections on HttpProxy ports', async
let httpProxyForwardCalled = false;
const proxy = new SmartProxy({
useHttpProxy: [8080],
httpProxyPort: 8844,
useHttpProxy: [8082], // Use different port to avoid conflicts
httpProxyPort: 8848, // Use different port to avoid conflicts
routes: [{
name: 'test-route',
match: {
ports: 8080
ports: 8082
},
action: {
type: 'forward',
@ -126,7 +128,7 @@ tap.test('should properly detect non-TLS connections on HttpProxy ports', async
const client = new net.Socket();
await new Promise<void>((resolve, reject) => {
client.connect(8080, 'localhost', () => {
client.connect(8082, 'localhost', () => {
console.log('Connected to proxy');
client.write('GET / HTTP/1.1\r\nHost: test.local\r\n\r\n');
resolve();
@ -147,8 +149,11 @@ tap.test('should properly detect non-TLS connections on HttpProxy ports', async
targetServer.close(() => resolve());
});
// Wait a bit to ensure port is released
await new Promise(resolve => setTimeout(resolve, 100));
// Restore original method
proxy['httpProxyBridge'].forwardToHttpProxy = originalForward;
});
tap.start();
export default tap.start();

View File

@ -1,59 +0,0 @@
import { expect, tap } from '@git.zone/tstest/tapbundle';
import * as net from 'net';
import { SmartProxy } from '../ts/index.js';
tap.test('simple socket handler test', async () => {
const proxy = new SmartProxy({
routes: [{
name: 'simple-handler',
match: {
ports: 8888
// No domains restriction - will match all connections on this port
},
action: {
type: 'socket-handler',
socketHandler: (socket, context) => {
console.log('Handler called!');
socket.write('HELLO\n');
socket.end();
}
}
}],
enableDetailedLogging: true
});
await proxy.start();
// Test connection
const client = new net.Socket();
let response = '';
client.on('data', (data) => {
response += data.toString();
});
await new Promise<void>((resolve, reject) => {
client.connect(8888, 'localhost', () => {
console.log('Connected');
// Send some initial data to trigger the handler
client.write('test\n');
resolve();
});
client.on('error', reject);
});
// Wait for response
await new Promise(resolve => {
client.on('close', () => {
console.log('Connection closed');
resolve(undefined);
});
});
console.log('Got response:', response);
expect(response).toEqual('HELLO\n');
await proxy.stop();
});
export default tap.start();