Download scripts/proxy-utils.mjs from SaylorTwift/openhands: direct link, hf CLI and curl.
- Browser
- Download file 8.6 kB
-
https://huggingface.co/SaylorTwift/openhands/resolve/main/scripts/proxy-utils.mjs
- Command line
-
hf download hf://SaylorTwift/openhands/scripts/proxy-utils.mjs
-
curl -L -o proxy-utils.mjs https://huggingface.co/SaylorTwift/openhands/resolve/main/scripts/proxy-utils.mjs
8.6 kB
| import { request as httpRequest } from "node:http"; | |
| import { request as httpsRequest } from "node:https"; | |
| import { createProxyServer } from "httpxy"; | |
| const DEFAULT_PROXY_TIMEOUT_MS = 120_000; | |
| const SERVER_INFO_PATH = "/server_info"; | |
| const BENIGN_SOCKET_ERRORS = new Set([ | |
| "ECONNRESET", | |
| "EPIPE", | |
| "ECONNABORTED", | |
| "ERR_STREAM_PREMATURE_CLOSE", | |
| ]); | |
| export function matchesPathPrefix(url, prefix) { | |
| return ( | |
| url === prefix || | |
| url.startsWith(prefix + "/") || | |
| url.startsWith(prefix + "?") | |
| ); | |
| } | |
| export function createRouter(routes, defaultBackend = null) { | |
| const sortedRoutes = Object.entries(routes).sort( | |
| ([a], [b]) => b.length - a.length, | |
| ); | |
| return function route(url) { | |
| for (const [prefix, backend] of sortedRoutes) { | |
| if (matchesPathPrefix(url, prefix)) { | |
| return backend; | |
| } | |
| } | |
| return defaultBackend; | |
| }; | |
| } | |
| export function isBenignSocketError(err) { | |
| return Boolean(err && BENIGN_SOCKET_ERRORS.has(err.code)); | |
| } | |
| function parseBackendUrl(backendUrl) { | |
| const url = new URL(backendUrl); | |
| if (url.protocol !== "http:" && url.protocol !== "https:") { | |
| throw new Error("Invalid backend URL"); | |
| } | |
| return { | |
| hostname: url.hostname, | |
| port: Number.parseInt(url.port, 10) || (url.protocol === "https:" ? 443 : 80), | |
| protocol: url.protocol, | |
| }; | |
| } | |
| function writeInvalidBackendUrlResponse(req, res) { | |
| const message = "Invalid backend URL"; | |
| console.error(`Proxy error for ${req.url}: ${message}`); | |
| if (!res.headersSent) { | |
| res.writeHead(502, { "Content-Type": "text/plain; charset=utf-8" }); | |
| res.end(`Bad Gateway: ${message}`); | |
| } else { | |
| res.destroy(); | |
| } | |
| } | |
| export function isServerInfoRequest(req) { | |
| const pathname = new URL(req.url ?? "/", "http://localhost").pathname; | |
| return pathname === SERVER_INFO_PATH; | |
| } | |
| export function proxyServerInfoRequest( | |
| req, | |
| res, | |
| backendUrl, | |
| runtimeServicesInfo, | |
| ) { | |
| let backend; | |
| try { | |
| backend = parseBackendUrl(backendUrl); | |
| } catch { | |
| writeInvalidBackendUrlResponse(req, res); | |
| return; | |
| } | |
| const request = backend.protocol === "https:" ? httpsRequest : httpRequest; | |
| const proxyReq = request( | |
| { | |
| hostname: backend.hostname, | |
| port: backend.port, | |
| path: req.url, | |
| method: req.method, | |
| headers: { | |
| ...req.headers, | |
| host: `${backend.hostname}:${backend.port}`, | |
| }, | |
| }, | |
| (proxyRes) => { | |
| const chunks = []; | |
| proxyRes.on("data", (chunk) => { | |
| chunks.push(Buffer.from(chunk)); | |
| }); | |
| proxyRes.on("error", (err) => { | |
| if (!isBenignSocketError(err)) { | |
| console.error(`Upstream response error for ${req.url}:`, err.message); | |
| } | |
| if (!res.headersSent) { | |
| res.writeHead(502); | |
| res.end(`Bad Gateway: ${err.message}`); | |
| } else { | |
| res.destroy(); | |
| } | |
| }); | |
| proxyRes.on("end", () => { | |
| const statusCode = proxyRes.statusCode ?? 502; | |
| const headers = { ...proxyRes.headers }; | |
| const originalBody = Buffer.concat(chunks); | |
| if (statusCode < 200 || statusCode >= 300 || req.method === "HEAD") { | |
| res.writeHead(statusCode, headers); | |
| res.end(req.method === "HEAD" ? "" : originalBody); | |
| return; | |
| } | |
| try { | |
| const serverInfo = JSON.parse(originalBody.toString("utf8")); | |
| const runtimeServices = | |
| typeof runtimeServicesInfo === "string" | |
| ? JSON.parse(runtimeServicesInfo) | |
| : runtimeServicesInfo; | |
| const body = Buffer.from( | |
| JSON.stringify({ | |
| ...serverInfo, | |
| runtime_services: runtimeServices, | |
| }), | |
| "utf8", | |
| ); | |
| delete headers["content-length"]; | |
| delete headers["transfer-encoding"]; | |
| headers["content-type"] = "application/json; charset=utf-8"; | |
| headers["cache-control"] = "no-store"; | |
| res.writeHead(statusCode, headers); | |
| res.end(body); | |
| } catch (err) { | |
| console.warn( | |
| `Could not append runtime_services to ${SERVER_INFO_PATH}: ${ | |
| err instanceof Error ? err.message : String(err) | |
| }`, | |
| ); | |
| res.writeHead(statusCode, headers); | |
| res.end(originalBody); | |
| } | |
| }); | |
| }, | |
| ); | |
| proxyReq.on("error", (err) => { | |
| if (!isBenignSocketError(err)) { | |
| console.error(`Proxy error for ${req.url}:`, err.message); | |
| } | |
| if (!res.headersSent) { | |
| res.writeHead(502); | |
| res.end(`Bad Gateway: ${err.message}`); | |
| } else { | |
| res.destroy(); | |
| } | |
| }); | |
| req.on("error", (err) => { | |
| if (!isBenignSocketError(err)) { | |
| console.error(`Client request error for ${req.url}:`, err.message); | |
| } | |
| proxyReq.destroy(); | |
| }); | |
| res.on("error", (err) => { | |
| if (!isBenignSocketError(err)) { | |
| console.error(`Client response error for ${req.url}:`, err.message); | |
| } | |
| proxyReq.destroy(); | |
| }); | |
| req.pipe(proxyReq, { end: true }); | |
| } | |
| function once(fn) { | |
| let called = false; | |
| return (...args) => { | |
| if (called) return; | |
| called = true; | |
| fn(...args); | |
| }; | |
| } | |
| function writeProxyError(res, message) { | |
| if (res.destroyed) return; | |
| if (!res.headersSent) { | |
| res.writeHead(502, { "Content-Type": "text/plain; charset=utf-8" }); | |
| res.end(`Bad Gateway: ${message}`); | |
| return; | |
| } | |
| res.destroy(); | |
| } | |
| export function createProxyHandlers({ | |
| label = "proxy", | |
| timeout = DEFAULT_PROXY_TIMEOUT_MS, | |
| proxyTimeout = DEFAULT_PROXY_TIMEOUT_MS, | |
| } = {}) { | |
| const proxy = createProxyServer({ | |
| ws: true, | |
| changeOrigin: true, | |
| xfwd: true, | |
| timeout, | |
| proxyTimeout, | |
| }); | |
| const metrics = { | |
| activeHttpRequests: 0, | |
| activeWebSockets: 0, | |
| totalHttpRequests: 0, | |
| totalWebSockets: 0, | |
| totalErrors: 0, | |
| }; | |
| proxy.on("error", (err, _req, resOrSocket, target) => { | |
| metrics.totalErrors += 1; | |
| const targetText = target ? ` -> ${target}` : ""; | |
| if (!isBenignSocketError(err)) { | |
| console.error(`[${label}] Proxy error${targetText}: ${err.message}`); | |
| } | |
| if (resOrSocket && typeof resOrSocket.writeHead === "function") { | |
| writeProxyError(resOrSocket, err.message); | |
| } else if (resOrSocket && typeof resOrSocket.destroy === "function") { | |
| resOrSocket.destroy(); | |
| } | |
| }); | |
| function proxyHttp(req, res, target) { | |
| metrics.activeHttpRequests += 1; | |
| metrics.totalHttpRequests += 1; | |
| const finish = once(() => { | |
| metrics.activeHttpRequests = Math.max(0, metrics.activeHttpRequests - 1); | |
| }); | |
| res.on("close", finish); | |
| res.on("finish", finish); | |
| res.on("error", finish); | |
| const handleProxyError = (err) => { | |
| metrics.totalErrors += 1; | |
| if (!isBenignSocketError(err)) { | |
| console.error( | |
| `[${label}] Proxy error for ${req.url} -> ${target}:`, | |
| err, | |
| ); | |
| } | |
| writeProxyError(res, err instanceof Error ? err.message : String(err)); | |
| finish(); | |
| }; | |
| try { | |
| proxy.web(req, res, { target }).catch(handleProxyError); | |
| } catch (err) { | |
| handleProxyError(err); | |
| } | |
| } | |
| function proxyWebSocket(req, socket, head, target) { | |
| metrics.activeWebSockets += 1; | |
| metrics.totalWebSockets += 1; | |
| const finish = once(() => { | |
| metrics.activeWebSockets = Math.max(0, metrics.activeWebSockets - 1); | |
| }); | |
| socket.on("close", finish); | |
| socket.on("error", finish); | |
| try { | |
| proxy.ws(req, socket, { target }, head).catch((err) => { | |
| metrics.totalErrors += 1; | |
| if (!isBenignSocketError(err)) { | |
| console.error( | |
| `[${label}] WebSocket proxy error for ${req.url} -> ${target}:`, | |
| err, | |
| ); | |
| } | |
| socket.destroy(); | |
| finish(); | |
| }); | |
| } catch (err) { | |
| metrics.totalErrors += 1; | |
| if (!isBenignSocketError(err)) { | |
| console.error( | |
| `[${label}] WebSocket proxy error for ${req.url} -> ${target}:`, | |
| err, | |
| ); | |
| } | |
| socket.destroy(); | |
| finish(); | |
| } | |
| } | |
| function dumpMetrics() { | |
| console.log( | |
| `[${label}] active_http=${metrics.activeHttpRequests} ` + | |
| `active_ws=${metrics.activeWebSockets} ` + | |
| `total_http=${metrics.totalHttpRequests} ` + | |
| `total_ws=${metrics.totalWebSockets} ` + | |
| `total_errors=${metrics.totalErrors}`, | |
| ); | |
| } | |
| function installDiagnostics(signal = "SIGUSR1") { | |
| process.on(signal, dumpMetrics); | |
| return () => { | |
| process.off(signal, dumpMetrics); | |
| }; | |
| } | |
| return { | |
| proxyHttp, | |
| proxyWebSocket, | |
| dumpMetrics, | |
| installDiagnostics, | |
| metrics, | |
| }; | |
| } | |