fix(smartproxy): Fix route security configuration location and improve ACME timing tests and socket mock implementations

This commit is contained in:
2025-05-29 14:34:00 +00:00
parent e6b3ae395c
commit 32583f784f
8 changed files with 155 additions and 60 deletions

View File

@ -41,7 +41,12 @@ tap.test('should detect and forward non-TLS connections on useHttpProxy ports',
}),
initiateCleanupOnce: () => {},
cleanupConnection: () => {},
getConnectionCount: () => 1
getConnectionCount: () => 1,
handleError: (type: string, record: any) => {
return (error: Error) => {
console.log(`Mock: Error handled for ${type}: ${error.message}`);
};
}
};
// Mock route manager that returns a matching route
@ -49,7 +54,11 @@ tap.test('should detect and forward non-TLS connections on useHttpProxy ports',
findMatchingRoute: (criteria: any) => ({
route: mockSettings.routes[0]
}),
getAllRoutes: () => mockSettings.routes
getAllRoutes: () => mockSettings.routes,
getRoutesForPort: (port: number) => mockSettings.routes.filter(r => {
const ports = Array.isArray(r.match.ports) ? r.match.ports : [r.match.ports];
return ports.includes(port);
})
};
// Mock security manager
@ -75,15 +84,33 @@ tap.test('should detect and forward non-TLS connections on useHttpProxy ports',
};
// Test: Create a mock socket representing non-TLS connection on port 8080
const mockSocket = Object.create(net.Socket.prototype) as net.Socket;
Object.defineProperty(mockSocket, 'localPort', { value: 8080, writable: false });
Object.defineProperty(mockSocket, 'remoteAddress', { value: '127.0.0.1', writable: false });
const mockSocket = {
localPort: 8080,
remoteAddress: '127.0.0.1',
on: function(event: string, handler: Function) { return this; },
once: function(event: string, handler: Function) {
// Capture the data handler
if (event === 'data') {
this._dataHandler = handler;
}
return this;
},
end: () => {},
destroy: () => {},
pause: () => {},
resume: () => {},
removeListener: function() { return this; },
emit: () => {},
_dataHandler: null as any
} as any;
// Simulate the handler processing the connection
handler.handleConnection(mockSocket);
// Simulate receiving non-TLS data
mockSocket.emit('data', Buffer.from('GET / HTTP/1.1\r\nHost: test.local\r\n\r\n'));
if (mockSocket._dataHandler) {
mockSocket._dataHandler(Buffer.from('GET / HTTP/1.1\r\nHost: test.local\r\n\r\n'));
}
// Give it a moment to process
await new Promise(resolve => setTimeout(resolve, 100));
@ -91,8 +118,6 @@ tap.test('should detect and forward non-TLS connections on useHttpProxy ports',
// Verify that the connection was forwarded to HttpProxy, not direct connection
expect(httpProxyForwardCalled).toEqual(true);
expect(directConnectionCalled).toEqual(false);
mockSocket.destroy();
});
// Test that verifies TLS connections still work normally
@ -130,7 +155,12 @@ tap.test('should handle TLS connections normally', async (tapTest) => {
}),
initiateCleanupOnce: () => {},
cleanupConnection: () => {},
getConnectionCount: () => 1
getConnectionCount: () => 1,
handleError: (type: string, record: any) => {
return (error: Error) => {
console.log(`Mock: Error handled for ${type}: ${error.message}`);
};
}
};
const mockTlsManager = {
@ -143,7 +173,11 @@ tap.test('should handle TLS connections normally', async (tapTest) => {
findMatchingRoute: (criteria: any) => ({
route: mockSettings.routes[0]
}),
getAllRoutes: () => mockSettings.routes
getAllRoutes: () => mockSettings.routes,
getRoutesForPort: (port: number) => mockSettings.routes.filter(r => {
const ports = Array.isArray(r.match.ports) ? r.match.ports : [r.match.ports];
return ports.includes(port);
})
};
const mockSecurityManager = {
@ -160,22 +194,38 @@ tap.test('should handle TLS connections normally', async (tapTest) => {
mockRouteManager as any
);
const mockSocket = Object.create(net.Socket.prototype) as net.Socket;
Object.defineProperty(mockSocket, 'localPort', { value: 443, writable: false });
Object.defineProperty(mockSocket, 'remoteAddress', { value: '127.0.0.1', writable: false });
const mockSocket = {
localPort: 443,
remoteAddress: '127.0.0.1',
on: function(event: string, handler: Function) { return this; },
once: function(event: string, handler: Function) {
// Capture the data handler
if (event === 'data') {
this._dataHandler = handler;
}
return this;
},
end: () => {},
destroy: () => {},
pause: () => {},
resume: () => {},
removeListener: function() { return this; },
emit: () => {},
_dataHandler: null as any
} as any;
handler.handleConnection(mockSocket);
// Simulate TLS handshake
const tlsHandshake = Buffer.from([0x16, 0x03, 0x01, 0x00, 0x05]);
mockSocket.emit('data', tlsHandshake);
if (mockSocket._dataHandler) {
const tlsHandshake = Buffer.from([0x16, 0x03, 0x01, 0x00, 0x05]);
mockSocket._dataHandler(tlsHandshake);
}
await new Promise(resolve => setTimeout(resolve, 100));
// TLS connections with 'terminate' mode should go to HttpProxy
expect(httpProxyForwardCalled).toEqual(true);
mockSocket.destroy();
});
tap.start();
export default tap.start();