feat(PortProxy): Enhanced PortProxy with custom target host and improved testing
This commit is contained in:
		| @@ -1,5 +1,13 @@ | ||||
| # Changelog | ||||
|  | ||||
| ## 2025-02-21 - 3.4.0 - feat(PortProxy) | ||||
| Enhanced PortProxy with custom target host and improved testing | ||||
|  | ||||
| - PortProxy constructor now accepts 'fromPort', 'toPort', and optional 'toHost' directly from settings | ||||
| - Refactored test cases to cover forwarding to the custom host | ||||
| - Added support to handle multiple concurrent connections | ||||
| - Refactored internal connection handling logic to utilize default configurations | ||||
|  | ||||
| ## 2025-02-21 - 3.3.1 - fix(PortProxy) | ||||
| fixed import usage of net and tls libraries for PortProxy | ||||
|  | ||||
|   | ||||
| @@ -58,7 +58,10 @@ function createTestClient(port: number, data: string): Promise<string> { | ||||
| // Setup test environment | ||||
| tap.test('setup port proxy test environment', async () => { | ||||
|   testServer = await createTestServer(TEST_SERVER_PORT); | ||||
|   portProxy = new PortProxy(PROXY_PORT, TEST_SERVER_PORT, { | ||||
|   portProxy = new PortProxy({ | ||||
|     fromPort: PROXY_PORT, | ||||
|     toPort: TEST_SERVER_PORT, | ||||
|     toHost: 'localhost', | ||||
|     domains: [], | ||||
|     sniEnabled: false, | ||||
|     defaultAllowedIPs: ['127.0.0.1', '::ffff:127.0.0.1'] | ||||
| @@ -70,11 +73,28 @@ tap.test('should start port proxy', async () => { | ||||
|   expect(portProxy.netServer.listening).toBeTrue(); | ||||
| }); | ||||
|  | ||||
| tap.test('should forward TCP connections and data', async () => { | ||||
| tap.test('should forward TCP connections and data to localhost', async () => { | ||||
|   const response = await createTestClient(PROXY_PORT, TEST_DATA); | ||||
|   expect(response).toEqual(`Echo: ${TEST_DATA}`); | ||||
| }); | ||||
|  | ||||
| tap.test('should forward TCP connections to custom host', async () => { | ||||
|   // Create a new proxy instance with a custom host | ||||
|   const customHostProxy = new PortProxy({ | ||||
|     fromPort: PROXY_PORT + 1, | ||||
|     toPort: TEST_SERVER_PORT, | ||||
|     toHost: '127.0.0.1', | ||||
|     domains: [], | ||||
|     sniEnabled: false, | ||||
|     defaultAllowedIPs: ['127.0.0.1', '::ffff:127.0.0.1'] | ||||
|   }); | ||||
|    | ||||
|   await customHostProxy.start(); | ||||
|   const response = await createTestClient(PROXY_PORT + 1, TEST_DATA); | ||||
|   expect(response).toEqual(`Echo: ${TEST_DATA}`); | ||||
|   await customHostProxy.stop(); | ||||
| }); | ||||
|  | ||||
| tap.test('should handle multiple concurrent connections', async () => { | ||||
|   const concurrentRequests = 5; | ||||
|   const requests = Array(concurrentRequests).fill(null).map((_, i) =>  | ||||
|   | ||||
| @@ -3,6 +3,6 @@ | ||||
|  */ | ||||
| export const commitinfo = { | ||||
|   name: '@push.rocks/smartproxy', | ||||
|   version: '3.3.1', | ||||
|   version: '3.4.0', | ||||
|   description: 'a proxy for handling high workloads of proxying' | ||||
| } | ||||
|   | ||||
| @@ -6,23 +6,27 @@ export interface DomainConfig { | ||||
|   allowedIPs: string[];  // glob patterns for IPs allowed to access this domain | ||||
| } | ||||
|  | ||||
| export interface ProxySettings { | ||||
| export interface ProxySettings extends plugins.tls.TlsOptions { | ||||
|   // Port configuration | ||||
|   fromPort: number; | ||||
|   toPort: number; | ||||
|   toHost?: string;  // Target host to proxy to, defaults to 'localhost' | ||||
|  | ||||
|   // Domain and security settings | ||||
|   domains: DomainConfig[]; | ||||
|   sniEnabled?: boolean; | ||||
|   tlsOptions?: plugins.tls.TlsOptions; | ||||
|   defaultAllowedIPs?: string[];  // Optional default IP patterns if no matching domain found | ||||
| } | ||||
|  | ||||
| export class PortProxy { | ||||
|   netServer: plugins.net.Server | plugins.tls.Server; | ||||
|   fromPort: number; | ||||
|   toPort: number; | ||||
|   settings: ProxySettings; | ||||
|  | ||||
|   constructor(fromPortArg: number, toPortArg: number, settings: plugins.tls.TlsOptions & ProxySettings) { | ||||
|     this.fromPort = fromPortArg; | ||||
|     this.toPort = toPortArg; | ||||
|     this.settings = settings; | ||||
|   constructor(settings: ProxySettings) { | ||||
|     this.settings = { | ||||
|       ...settings, | ||||
|       toHost: settings.toHost || 'localhost' | ||||
|     }; | ||||
|   } | ||||
|  | ||||
|   public async start() { | ||||
| @@ -44,7 +48,9 @@ export class PortProxy { | ||||
|       return this.settings.domains.find(config => plugins.minimatch(serverName, config.domain)); | ||||
|     }; | ||||
|  | ||||
|     const server = this.settings.sniEnabled ? plugins.tls.createServer(this.settings.tlsOptions || {}) : plugins.net.createServer(); | ||||
|     const server = this.settings.sniEnabled | ||||
|       ? plugins.tls.createServer(this.settings) | ||||
|       : plugins.net.createServer(); | ||||
|      | ||||
|     this.netServer = server.on('connection', (from: plugins.net.Socket) => { | ||||
|       const remoteIP = from.remoteAddress || ''; | ||||
| @@ -74,8 +80,8 @@ export class PortProxy { | ||||
|         } | ||||
|  | ||||
|         const to = plugins.net.createConnection({ | ||||
|           host: 'localhost', | ||||
|           port: this.toPort, | ||||
|           host: this.settings.toHost!, | ||||
|           port: this.settings.toPort, | ||||
|         }); | ||||
|         from.setTimeout(120000); | ||||
|         from.pipe(to); | ||||
| @@ -105,8 +111,8 @@ export class PortProxy { | ||||
|           cleanUpSockets(from, to); | ||||
|         }); | ||||
|       }) | ||||
|       .listen(this.fromPort); | ||||
|     console.log(`PortProxy -> OK: Now listening on port ${this.fromPort}`); | ||||
|       .listen(this.settings.fromPort); | ||||
|     console.log(`PortProxy -> OK: Now listening on port ${this.settings.fromPort}`); | ||||
|   } | ||||
|  | ||||
|   public async stop() { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user