import { tap, expect } from '@git.zone/tstest/tapbundle'; import * as net from 'net'; // Unit test for the HTTP forwarding fix tap.test('should forward non-TLS connections on HttpProxy ports', async (tapTest) => { // Test configuration const testPort = 8080; const httpProxyPort = 8844; // Track forwarding logic let forwardedToHttpProxy = false; let setupDirectConnection = false; // Create mock settings const mockSettings = { useHttpProxy: [testPort], httpProxyPort: httpProxyPort, routes: [{ name: 'test-route', match: { ports: testPort }, action: { type: 'forward', target: { host: 'localhost', port: 8181 } } }] }; // Create mock connection record const mockRecord = { id: 'test-connection', localPort: testPort, remoteIP: '127.0.0.1', isTLS: false }; // Mock HttpProxyBridge const mockHttpProxyBridge = { getHttpProxy: () => ({ available: true }), forwardToHttpProxy: async () => { forwardedToHttpProxy = true; } }; // Test the logic from handleForwardAction const route = mockSettings.routes[0]; const action = route.action; // Simulate the fixed logic if (!action.tls) { // No TLS settings - check if this port should use HttpProxy const isHttpProxyPort = mockSettings.useHttpProxy?.includes(mockRecord.localPort); if (isHttpProxyPort && mockHttpProxyBridge.getHttpProxy()) { // Forward non-TLS connections to HttpProxy if configured console.log(`Using HttpProxy for non-TLS connection on port ${mockRecord.localPort}`); await mockHttpProxyBridge.forwardToHttpProxy(); } else { // Basic forwarding console.log(`Using basic forwarding`); setupDirectConnection = true; } } // Verify the fix works correctly expect(forwardedToHttpProxy).toEqual(true); expect(setupDirectConnection).toEqual(false); console.log('Test passed: Non-TLS connections on HttpProxy ports are forwarded correctly'); }); // Test that non-HttpProxy ports still use direct connection tap.test('should use direct connection for non-HttpProxy ports', async (tapTest) => { let forwardedToHttpProxy = false; let setupDirectConnection = false; const mockSettings = { useHttpProxy: [80, 443], // Different ports httpProxyPort: 8844, routes: [{ name: 'test-route', match: { ports: 8080 }, // Not in useHttpProxy action: { type: 'forward', target: { host: 'localhost', port: 8181 } } }] }; const mockRecord = { id: 'test-connection-2', localPort: 8080, // Not in useHttpProxy remoteIP: '127.0.0.1', isTLS: false }; const mockHttpProxyBridge = { getHttpProxy: () => ({ available: true }), forwardToHttpProxy: async () => { forwardedToHttpProxy = true; } }; const route = mockSettings.routes[0]; const action = route.action; // Test the logic if (!action.tls) { const isHttpProxyPort = mockSettings.useHttpProxy?.includes(mockRecord.localPort); if (isHttpProxyPort && mockHttpProxyBridge.getHttpProxy()) { console.log(`Using HttpProxy for non-TLS connection on port ${mockRecord.localPort}`); await mockHttpProxyBridge.forwardToHttpProxy(); } else { console.log(`Using basic forwarding for port ${mockRecord.localPort}`); setupDirectConnection = true; } } // Verify port 8080 uses direct connection when not in useHttpProxy expect(forwardedToHttpProxy).toEqual(false); expect(setupDirectConnection).toEqual(true); console.log('Test passed: Non-HttpProxy ports use direct connection'); }); // Test HTTP-01 ACME challenge scenario tap.test('should handle ACME HTTP-01 challenges on port 80 with HttpProxy', async (tapTest) => { let forwardedToHttpProxy = false; const mockSettings = { useHttpProxy: [80], // Port 80 configured for HttpProxy httpProxyPort: 8844, acme: { port: 80, email: 'test@example.com' }, routes: [{ name: 'acme-challenge', match: { ports: 80, paths: ['/.well-known/acme-challenge/*'] }, action: { type: 'forward', target: { host: 'localhost', port: 8080 } } }] }; const mockRecord = { id: 'acme-connection', localPort: 80, remoteIP: '127.0.0.1', isTLS: false }; const mockHttpProxyBridge = { getHttpProxy: () => ({ available: true }), forwardToHttpProxy: async () => { forwardedToHttpProxy = true; } }; const route = mockSettings.routes[0]; const action = route.action; // Test the fix for ACME HTTP-01 challenges if (!action.tls) { const isHttpProxyPort = mockSettings.useHttpProxy?.includes(mockRecord.localPort); if (isHttpProxyPort && mockHttpProxyBridge.getHttpProxy()) { console.log(`Using HttpProxy for ACME challenge on port ${mockRecord.localPort}`); await mockHttpProxyBridge.forwardToHttpProxy(); } } // Verify HTTP-01 challenges on port 80 go through HttpProxy expect(forwardedToHttpProxy).toEqual(true); console.log('Test passed: ACME HTTP-01 challenges on port 80 use HttpProxy'); }); tap.start();