From 5e8b435f3c777d0c3ff0a03563007e79fb7fa11e Mon Sep 17 00:00:00 2001 From: Massoud Valipoor Date: Sun, 18 May 2025 20:36:15 +0200 Subject: [PATCH] Refactor DAHR and Proxy classes for improved request handling - Updated DAHR to include action type in web2Request for better request management. - Simplified Proxy request handling by removing unnecessary CONNECT method logic and streamlining response processing. - Enhanced error handling and response data collection in Proxy class. - Adjusted proxy server configuration for better target URL management. --- src/features/web2/dahr/DAHR.ts | 9 +- src/features/web2/proxy/Proxy.ts | 168 +++++++------------------------ 2 files changed, 42 insertions(+), 135 deletions(-) diff --git a/src/features/web2/dahr/DAHR.ts b/src/features/web2/dahr/DAHR.ts index 2db132e69..d3912b0ba 100644 --- a/src/features/web2/dahr/DAHR.ts +++ b/src/features/web2/dahr/DAHR.ts @@ -8,6 +8,7 @@ import { Proxy } from "src/features/web2/proxy/Proxy" import { ProxyFactory } from "src/features/web2/proxy/ProxyFactory" import required from "src/utilities/required" import { generateUniqueId } from "src/utilities/generateUniqueId" +import { EnumWeb2Actions } from "@kynesyslabs/demosdk/types" /** * DAHR - Data Agnostic HTTPS Relay, class that handles the Web2 request and attestation process. @@ -71,7 +72,13 @@ export class DAHR { const web2RequestManager = new Web2RequestManager(this) const web2Response = await this._proxy.sendHTTPRequest({ - web2Request: this._web2Request, + web2Request: { + ...this._web2Request, + raw: { + ...this._web2Request.raw, + action: EnumWeb2Actions.START_PROXY, + }, + }, targetMethod: method, targetHeaders: headers, payload, diff --git a/src/features/web2/proxy/Proxy.ts b/src/features/web2/proxy/Proxy.ts index a8158a2e8..f460a114e 100644 --- a/src/features/web2/proxy/Proxy.ts +++ b/src/features/web2/proxy/Proxy.ts @@ -80,71 +80,47 @@ export class Proxy { const req = http.request({ hostname: this._proxyHost, port: this._proxyPort, - method: targetProtocol === "https:" ? "CONNECT" : targetMethod, - path: `${targetHostname}:${targetPort}`, + method: targetMethod, + path: "/", headers, timeout: 30000, - agent: false, }) - - req.on("connect", (res, socket) => { - if (res.statusCode !== 200) { - socket.destroy() - reject( - new Error( - `Tunnel connection failed: ${res.statusCode}`, - ), - ) - return - } - - // For HTTPS, establish the tunnel - const options = { - host: targetHostname, - port: targetPort, - method: targetMethod, - path: - new URL(targetUrl).pathname + new URL(targetUrl).search, - headers, - socket: socket, - agent: false, - } - - const httpsReq = https.request(options, httpsRes => { - let data = "" - httpsRes.on("data", chunk => (data += chunk)) - httpsRes.on("end", () => { - resolve({ - status: httpsRes.statusCode || 500, - statusText: httpsRes.statusMessage || "Unknown", - headers: httpsRes.headers, - data: data, - }) - }) + const chunks: Buffer[] = [] + let responseHeaders: http.IncomingHttpHeaders = {} + let statusCode = 500 + let statusMessage = "Unknown" + + req.on("response", res => { + statusCode = res.statusCode || 500 + statusMessage = res.statusMessage || "Unknown" + responseHeaders = res.headers + + res.on("data", chunk => { + chunks.push(Buffer.from(chunk)) }) - httpsReq.on("error", err => { - console.error("[Web2API] HTTPS request error:", err) - socket.destroy() - reject(err) + res.on("end", () => { + const data = Buffer.concat(chunks).toString() + resolve({ + status: statusCode, + statusText: statusMessage, + headers: responseHeaders, + data: data, + }) }) - - if ( - targetMethod !== EnumWeb2Methods.GET && - targetMethod !== EnumWeb2Methods.DELETE - ) { - httpsReq.write(JSON.stringify(payload)) - } - - httpsReq.end() }) req.on("error", error => { - console.error("[Web2API] Request error:", error) - reject(error) }) + if ( + targetMethod !== EnumWeb2Methods.GET && + targetMethod !== EnumWeb2Methods.DELETE + ) { + req.write(JSON.stringify(payload)) + } + req.end() }) } @@ -158,7 +134,6 @@ export class Proxy { stopProxy(): void { if (this._server) { this._server.close(() => { - console.log("[Web2API] Proxy server stopped") this._isInitialized = false this._server = null }) @@ -201,11 +176,7 @@ export class Proxy { // Create the proxy server const proxyServer = httpProxy.createProxyServer({ - target: { - protocol: targetProtocol, - host: targetHostname, - port: targetPort, - }, + target: targetUrl, changeOrigin: true, secure: false, // TODO: Enable SSL certificate verification before production ssl: @@ -218,7 +189,6 @@ export class Proxy { proxyServer.on("error", (err, req, res) => { console.error("[Web2API] Proxy server error:", err) if (res instanceof http.ServerResponse) { - console.log("[Web2API] Writing response") res.writeHead(500, { "Content-Type": "text/plain", }) @@ -238,78 +208,11 @@ export class Proxy { res.end("Unauthorized") return } - proxyServer.web(req, res) - }) - - // Handle HTTPS CONNECT - this._server.on("connect", (req, clientSocket, head) => { - if (!this.isAuthorizedRequest(req)) { - clientSocket.write( - "HTTP/1.1 403 Forbidden\r\nContent-Type: text/plain\r\n\r\nUnauthorized request", - ) - clientSocket.destroy() - return - } - const [targetHost, targetPort] = req.url.split(":") - const targetSocket = net.connect( - parseInt(targetPort) || 443, - targetHost, - () => { - try { - if ( - !clientSocket.destroyed && - clientSocket.writable - ) { - clientSocket.write( - "HTTP/1.1 200 Connection Established\r\n" + - "Proxy-agent: DAHR-Proxy\r\n" + - "\r\n", - ) - - if ( - !targetSocket.destroyed && - targetSocket.writable - ) { - targetSocket.write(head) - - // Only set up pipes if both sockets are still valid - if ( - !clientSocket.destroyed && - !targetSocket.destroyed - ) { - targetSocket.pipe(clientSocket) - clientSocket.pipe(targetSocket) - } - } - } - } catch (error) { - console.error( - "[Web2API] Error during connection setup:", - error, - ) - this.safelyCloseSocket(clientSocket) - this.safelyCloseSocket(targetSocket) - } - }, - ) - - targetSocket.on("error", err => { - console.error("[Web2API] Target connection error:", err) - this.safelyCloseSocket(clientSocket) - }) - - clientSocket.on("error", err => { - console.error("[Web2API] Client connection error:", err) - this.safelyCloseSocket(targetSocket) - }) - - targetSocket.on("end", () => { - this.safelyCloseSocket(clientSocket) - }) - - clientSocket.on("end", () => { - this.safelyCloseSocket(targetSocket) + proxyServer.web(req, res, { + target: targetUrl, + changeOrigin: true, + secure: false, }) }) @@ -318,9 +221,6 @@ export class Proxy { const address = this._server?.address() if (typeof address === "object" && address !== null) { this._proxyPort = address.port - console.log( - `[Web2API] Proxy server running at http://127.0.0.1:${this._proxyPort}/`, - ) resolve() } else { reject(new Error("[Web2API] Failed to get server address"))