fix(network-proxy/websocket): Improve WebSocket connection closure and update router integration
This commit is contained in:
		| @@ -1,5 +1,12 @@ | |||||||
| # Changelog | # Changelog | ||||||
|  |  | ||||||
|  | ## 2025-05-15 - 18.1.1 - fix(network-proxy/websocket) | ||||||
|  | Improve WebSocket connection closure and update router integration | ||||||
|  |  | ||||||
|  | - Wrap WS close logic in try-catch blocks to ensure valid close codes are used for both incoming and outgoing WebSocket connections | ||||||
|  | - Use explicit numeric close codes (defaulting to 1000 when unavailable) to prevent improper socket termination | ||||||
|  | - Update NetworkProxy updateRoutes to also refresh the WebSocket handler routes for consistent configuration | ||||||
|  |  | ||||||
| ## 2025-05-15 - 18.1.0 - feat(nftables) | ## 2025-05-15 - 18.1.0 - feat(nftables) | ||||||
| Add NFTables integration for kernel-level forwarding and update documentation, tests, and helper functions | Add NFTables integration for kernel-level forwarding and update documentation, tests, and helper functions | ||||||
|  |  | ||||||
|   | |||||||
| @@ -238,6 +238,10 @@ tap.test('should start the proxy server', async () => { | |||||||
|         }, |         }, | ||||||
|         tls: { |         tls: { | ||||||
|           mode: 'terminate' |           mode: 'terminate' | ||||||
|  |         }, | ||||||
|  |         websocket: { | ||||||
|  |           enabled: true, | ||||||
|  |           subprotocols: ['echo-protocol'] | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -3,6 +3,6 @@ | |||||||
|  */ |  */ | ||||||
| export const commitinfo = { | export const commitinfo = { | ||||||
|   name: '@push.rocks/smartproxy', |   name: '@push.rocks/smartproxy', | ||||||
|   version: '18.1.0', |   version: '18.1.1', | ||||||
|   description: 'A powerful proxy package with unified route-based configuration for high traffic management. Features include SSL/TLS support, flexible routing patterns, WebSocket handling, advanced security options, and automatic ACME certificate management.' |   description: 'A powerful proxy package with unified route-based configuration for high traffic management. Features include SSL/TLS support, flexible routing patterns, WebSocket handling, advanced security options, and automatic ACME certificate management.' | ||||||
| } | } | ||||||
|   | |||||||
| @@ -500,6 +500,9 @@ export class NetworkProxy implements IMetricsTracker { | |||||||
|       this.logger.warn('Router has no recognized configuration method'); |       this.logger.warn('Router has no recognized configuration method'); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // Update WebSocket handler with new routes | ||||||
|  |     this.webSocketHandler.setRoutes(routes); | ||||||
|  |  | ||||||
|     this.logger.info(`Route configuration updated with ${routes.length} routes and ${legacyConfigs.length} proxy configs`); |     this.logger.info(`Route configuration updated with ${routes.length} routes and ${legacyConfigs.length} proxy configs`); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -419,9 +419,15 @@ export class WebSocketHandler { | |||||||
|         wsIncoming.on('close', (code, reason) => { |         wsIncoming.on('close', (code, reason) => { | ||||||
|           this.logger.debug(`WebSocket client connection closed: ${code} ${reason}`); |           this.logger.debug(`WebSocket client connection closed: ${code} ${reason}`); | ||||||
|           if (wsOutgoing.readyState === wsOutgoing.OPEN) { |           if (wsOutgoing.readyState === wsOutgoing.OPEN) { | ||||||
|             const validCode = code || 1000; |             // Ensure code is a valid WebSocket close code number | ||||||
|             const reasonString = toBuffer(reason).toString(); |             const validCode = typeof code === 'number' && code >= 1000 && code <= 4999 ? code : 1000; | ||||||
|             wsOutgoing.close(validCode, reasonString); |             try { | ||||||
|  |               const reasonString = reason ? toBuffer(reason).toString() : ''; | ||||||
|  |               wsOutgoing.close(validCode, reasonString); | ||||||
|  |             } catch (err) { | ||||||
|  |               this.logger.error('Error closing wsOutgoing:', err); | ||||||
|  |               wsOutgoing.close(validCode); | ||||||
|  |             } | ||||||
|           } |           } | ||||||
|  |  | ||||||
|           // Clean up timers |           // Clean up timers | ||||||
| @@ -432,9 +438,15 @@ export class WebSocketHandler { | |||||||
|         wsOutgoing.on('close', (code, reason) => { |         wsOutgoing.on('close', (code, reason) => { | ||||||
|           this.logger.debug(`WebSocket target connection closed: ${code} ${reason}`); |           this.logger.debug(`WebSocket target connection closed: ${code} ${reason}`); | ||||||
|           if (wsIncoming.readyState === wsIncoming.OPEN) { |           if (wsIncoming.readyState === wsIncoming.OPEN) { | ||||||
|             const validCode = code || 1000; |             // Ensure code is a valid WebSocket close code number | ||||||
|             const reasonString = toBuffer(reason).toString(); |             const validCode = typeof code === 'number' && code >= 1000 && code <= 4999 ? code : 1000; | ||||||
|             wsIncoming.close(validCode, reasonString); |             try { | ||||||
|  |               const reasonString = reason ? toBuffer(reason).toString() : ''; | ||||||
|  |               wsIncoming.close(validCode, reasonString); | ||||||
|  |             } catch (err) { | ||||||
|  |               this.logger.error('Error closing wsIncoming:', err); | ||||||
|  |               wsIncoming.close(validCode); | ||||||
|  |             } | ||||||
|           } |           } | ||||||
|  |  | ||||||
|           // Clean up timers |           // Clean up timers | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user