update
This commit is contained in:
		| @@ -219,21 +219,12 @@ export class NetworkProxy implements IMetricsTracker { | ||||
|     }; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * @deprecated Use SmartCertManager instead | ||||
|    */ | ||||
|   public setExternalPort80Handler(handler: any): void { | ||||
|     this.logger.warn('Port80Handler is deprecated - use SmartCertManager instead'); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Starts the proxy server | ||||
|    */ | ||||
|   public async start(): Promise<void> { | ||||
|     this.startTime = Date.now(); | ||||
|      | ||||
|     // Certificate management is now handled by SmartCertManager | ||||
|      | ||||
|     // Create HTTP/2 server with HTTP/1 fallback | ||||
|     this.httpsServer = plugins.http2.createSecureServer( | ||||
|       { | ||||
|   | ||||
| @@ -47,6 +47,7 @@ export interface IRouteContext { | ||||
|   path?: string;         // URL path (for HTTP connections) | ||||
|   query?: string;        // Query string (for HTTP connections) | ||||
|   headers?: Record<string, string>; // HTTP headers (for HTTP connections) | ||||
|   method?: string;       // HTTP method (for HTTP connections) | ||||
|  | ||||
|   // TLS information | ||||
|   isTls: boolean;        // Whether the connection is TLS | ||||
|   | ||||
| @@ -728,45 +728,139 @@ export class RouteConnectionHandler { | ||||
|       return; | ||||
|     } | ||||
|      | ||||
|     try { | ||||
|       // Build route context | ||||
|       const context: IRouteContext = { | ||||
|         port: record.localPort, | ||||
|         domain: record.lockedDomain, | ||||
|         clientIp: record.remoteIP, | ||||
|         serverIp: socket.localAddress!, | ||||
|         path: undefined,  // Will need to be extracted from HTTP request | ||||
|         isTls: record.isTLS, | ||||
|         tlsVersion: record.tlsVersion, | ||||
|         routeName: route.name, | ||||
|         routeId: route.name, | ||||
|         timestamp: Date.now(), | ||||
|         connectionId | ||||
|       }; | ||||
|     let buffer = Buffer.alloc(0); | ||||
|      | ||||
|     const handleHttpData = async (chunk: Buffer) => { | ||||
|       buffer = Buffer.concat([buffer, chunk]); | ||||
|        | ||||
|       // Call the handler | ||||
|       const response = await route.action.handler(context); | ||||
|        | ||||
|       // Send HTTP response | ||||
|       const headers = response.headers || {}; | ||||
|       headers['Content-Length'] = Buffer.byteLength(response.body).toString(); | ||||
|        | ||||
|       let httpResponse = `HTTP/1.1 ${response.status} ${getStatusText(response.status)}\r\n`; | ||||
|       for (const [key, value] of Object.entries(headers)) { | ||||
|         httpResponse += `${key}: ${value}\r\n`; | ||||
|       // Look for end of HTTP headers | ||||
|       const headerEndIndex = buffer.indexOf('\r\n\r\n'); | ||||
|       if (headerEndIndex === -1) { | ||||
|         // Need more data | ||||
|         if (buffer.length > 8192) { // Prevent excessive buffering | ||||
|           console.error(`[${connectionId}] HTTP headers too large`); | ||||
|           socket.end(); | ||||
|           this.connectionManager.cleanupConnection(record, 'headers_too_large'); | ||||
|         } | ||||
|         return; | ||||
|       } | ||||
|       httpResponse += '\r\n'; | ||||
|        | ||||
|       socket.write(httpResponse); | ||||
|       socket.write(response.body); | ||||
|       socket.end(); | ||||
|       // Parse the HTTP request | ||||
|       const headerBuffer = buffer.slice(0, headerEndIndex); | ||||
|       const headers = headerBuffer.toString(); | ||||
|       const lines = headers.split('\r\n'); | ||||
|        | ||||
|       this.connectionManager.cleanupConnection(record, 'completed'); | ||||
|     } catch (error) { | ||||
|       console.error(`[${connectionId}] Error in static handler: ${error}`); | ||||
|       socket.end(); | ||||
|       this.connectionManager.cleanupConnection(record, 'handler_error'); | ||||
|     } | ||||
|       if (lines.length === 0) { | ||||
|         console.error(`[${connectionId}] Invalid HTTP request`); | ||||
|         socket.end(); | ||||
|         this.connectionManager.cleanupConnection(record, 'invalid_request'); | ||||
|         return; | ||||
|       } | ||||
|        | ||||
|       // Parse request line | ||||
|       const requestLine = lines[0]; | ||||
|       const requestParts = requestLine.split(' '); | ||||
|       if (requestParts.length < 3) { | ||||
|         console.error(`[${connectionId}] Invalid HTTP request line`); | ||||
|         socket.end(); | ||||
|         this.connectionManager.cleanupConnection(record, 'invalid_request_line'); | ||||
|         return; | ||||
|       } | ||||
|        | ||||
|       const [method, path, httpVersion] = requestParts; | ||||
|        | ||||
|       // Parse headers | ||||
|       const headersMap: Record<string, string> = {}; | ||||
|       for (let i = 1; i < lines.length; i++) { | ||||
|         const colonIndex = lines[i].indexOf(':'); | ||||
|         if (colonIndex > 0) { | ||||
|           const key = lines[i].slice(0, colonIndex).trim().toLowerCase(); | ||||
|           const value = lines[i].slice(colonIndex + 1).trim(); | ||||
|           headersMap[key] = value; | ||||
|         } | ||||
|       } | ||||
|        | ||||
|       // Extract query string if present | ||||
|       let pathname = path; | ||||
|       let query: string | undefined; | ||||
|       const queryIndex = path.indexOf('?'); | ||||
|       if (queryIndex !== -1) { | ||||
|         pathname = path.slice(0, queryIndex); | ||||
|         query = path.slice(queryIndex + 1); | ||||
|       } | ||||
|        | ||||
|       try { | ||||
|         // Build route context with parsed HTTP information | ||||
|         const context: IRouteContext = { | ||||
|           port: record.localPort, | ||||
|           domain: record.lockedDomain || headersMap['host']?.split(':')[0], | ||||
|           clientIp: record.remoteIP, | ||||
|           serverIp: socket.localAddress!, | ||||
|           path: pathname, | ||||
|           query: query, | ||||
|           headers: headersMap, | ||||
|           method: method, | ||||
|           isTls: record.isTLS, | ||||
|           tlsVersion: record.tlsVersion, | ||||
|           routeName: route.name, | ||||
|           routeId: route.name, | ||||
|           timestamp: Date.now(), | ||||
|           connectionId | ||||
|         }; | ||||
|          | ||||
|         // Remove the data listener since we're handling the request | ||||
|         socket.removeListener('data', handleHttpData); | ||||
|          | ||||
|         // Call the handler with the properly parsed context | ||||
|         const response = await route.action.handler(context); | ||||
|          | ||||
|         // Prepare the HTTP response | ||||
|         const responseHeaders = response.headers || {}; | ||||
|         const contentLength = Buffer.byteLength(response.body || ''); | ||||
|         responseHeaders['Content-Length'] = contentLength.toString(); | ||||
|          | ||||
|         if (!responseHeaders['Content-Type']) { | ||||
|           responseHeaders['Content-Type'] = 'text/plain'; | ||||
|         } | ||||
|          | ||||
|         // Build the response | ||||
|         let httpResponse = `HTTP/1.1 ${response.status} ${getStatusText(response.status)}\r\n`; | ||||
|         for (const [key, value] of Object.entries(responseHeaders)) { | ||||
|           httpResponse += `${key}: ${value}\r\n`; | ||||
|         } | ||||
|         httpResponse += '\r\n'; | ||||
|          | ||||
|         // Send response | ||||
|         socket.write(httpResponse); | ||||
|         if (response.body) { | ||||
|           socket.write(response.body); | ||||
|         } | ||||
|         socket.end(); | ||||
|          | ||||
|         this.connectionManager.cleanupConnection(record, 'completed'); | ||||
|       } catch (error) { | ||||
|         console.error(`[${connectionId}] Error in static handler: ${error}`); | ||||
|          | ||||
|         // Send error response | ||||
|         const errorResponse = 'HTTP/1.1 500 Internal Server Error\r\n' + | ||||
|                             'Content-Type: text/plain\r\n' + | ||||
|                             'Content-Length: 21\r\n' + | ||||
|                             '\r\n' + | ||||
|                             'Internal Server Error'; | ||||
|         socket.write(errorResponse); | ||||
|         socket.end(); | ||||
|          | ||||
|         this.connectionManager.cleanupConnection(record, 'handler_error'); | ||||
|       } | ||||
|     }; | ||||
|      | ||||
|     // Listen for data | ||||
|     socket.on('data', handleHttpData); | ||||
|      | ||||
|     // Ensure cleanup on socket close | ||||
|     socket.once('close', () => { | ||||
|       socket.removeListener('data', handleHttpData); | ||||
|     }); | ||||
|   } | ||||
|    | ||||
|   /** | ||||
|   | ||||
		Reference in New Issue
	
	Block a user