update
This commit is contained in:
		| @@ -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" | ||||
| } | ||||
| @@ -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, | ||||
|   | ||||
| @@ -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(); | ||||
| @@ -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', | ||||
|   | ||||
| @@ -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 = { | ||||
|   | ||||
| @@ -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(); | ||||
| @@ -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(); | ||||
		Reference in New Issue
	
	Block a user