UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

160 lines (159 loc) • 5.12 kB
import { i as normalizeTlsFingerprint } from "./client-address-utils-BafGwQBm.mjs"; import { r as registerManagedProxyGatewayLoopbackBypass } from "./proxy-lifecycle-DmxzSuk6.mjs"; import { n as createNodeProxyAgent } from "./node-proxy-agent-D_aqMs2B.mjs"; import { Agent, request } from "node:http"; import { Agent as Agent$1, request as request$1 } from "node:https"; import { TLSSocket } from "node:tls"; //#region src/gateway/local-http-probe.ts const GATEWAY_HTTP_PROBE_MAX_RESPONSE_CHARS = 1024; const directHttpAgent = new Agent({ keepAlive: false }); const directHttpsAgent = new Agent$1({ keepAlive: false, maxCachedSessions: 0 }); function normalizeGatewayHttpProbeHost(host) { return host === "0.0.0.0" || host === "::" ? "127.0.0.1" : host; } async function requestGatewayLocalHttpProbe(params) { params.signal?.throwIfAborted(); if (params.timeoutMs <= 0) return null; const response = await new Promise((resolve) => { let settled = false; const finish = (result) => { if (settled) return; settled = true; clearTimeout(deadline); resolve(result); }; const pins = params.tlsFingerprints?.map(normalizeTlsFingerprint); const host = normalizeGatewayHttpProbeHost(params.host); const protocol = pins ? "https" : "http"; const targetUrl = `${protocol}://${host.includes(":") ? `[${host}]` : host}:${params.port}${params.pathname}`; registerManagedProxyGatewayLoopbackBypass(targetUrl); const proxyAgent = createNodeProxyAgent({ mode: "env", targetUrl, protocol, agentOptions: { keepAlive: false, maxCachedSessions: 0 } }); const req = (pins ? request$1 : request)({ hostname: host, port: params.port, path: params.pathname, method: "GET", timeout: params.timeoutMs, agent: proxyAgent ?? (pins ? directHttpsAgent : directHttpAgent), ...params.signal ? { signal: params.signal } : {}, ...pins ? { rejectUnauthorized: false } : {} }, (res) => { let tlsFingerprint; if (pins) { tlsFingerprint = res.socket instanceof TLSSocket ? normalizeTlsFingerprint(res.socket.getPeerCertificate().fingerprint256 ?? "") : ""; if (!tlsFingerprint || !pins.includes(tlsFingerprint)) { res.resume(); finish(null); return; } } let body = ""; res.setEncoding("utf8"); res.on("data", (chunk) => { if (body.length + chunk.length > GATEWAY_HTTP_PROBE_MAX_RESPONSE_CHARS) { res.destroy(); finish(null); return; } body += chunk; }); res.once("end", () => { finish({ statusCode: res.statusCode ?? 0, body, ...tlsFingerprint ? { tlsFingerprint } : {} }); }); res.once("error", () => { finish(null); }); }); const deadline = setTimeout(() => { req.destroy(); finish(null); }, params.timeoutMs); req.once("timeout", () => { req.destroy(); finish(null); }); req.once("error", () => { finish(null); }); req.once("close", () => proxyAgent?.destroy()); req.end(); }); params.signal?.throwIfAborted(); return response; } function createConfiguredGatewayLocalProbe(config) { const tlsConfig = config.gateway?.tls; let configured; let inspection; let verified; const inspectCertificate = () => inspection ??= import("./gateway-DqyRdtMn.mjs").then(async ({ inspectGatewayTlsCertificate }) => { const certificate = await inspectGatewayTlsCertificate(tlsConfig); if (!certificate.ok) return; const fingerprint = certificate.value.fingerprintSha256; if (configured?.fingerprint !== fingerprint) configured = { fingerprint, generation: (configured?.generation ?? 0) + 1 }; return configured; }).catch(() => void 0).finally(() => { inspection = void 0; }); const requestHttp = async (params) => { params.signal?.throwIfAborted(); const endpoint = `${normalizeGatewayHttpProbeHost(params.host)}:${params.port}`; const previous = verified; let candidate; let tlsFingerprints; if (tlsConfig?.enabled === true) { candidate = await inspectCertificate(); params.signal?.throwIfAborted(); tlsFingerprints = [...candidate ? [candidate.fingerprint] : [], ...previous?.endpoint === endpoint ? [previous.fingerprint] : []]; if (tlsFingerprints.length === 0) return null; } const result = await requestGatewayLocalHttpProbe({ ...params, tlsFingerprints }); const accepted = result?.tlsFingerprint === candidate?.fingerprint ? candidate : previous; if (result?.tlsFingerprint && accepted && (verified?.endpoint !== endpoint || accepted.generation >= verified.generation)) verified = { ...accepted, endpoint }; return result; }; return { requestHttp, async resolveWebSocketTarget(port, signal) { signal?.throwIfAborted(); if (tlsConfig?.enabled !== true) return { url: `ws://127.0.0.1:${port}` }; const response = await requestHttp({ host: "127.0.0.1", port, pathname: "/healthz", timeoutMs: 3e3, signal }); return response?.tlsFingerprint ? { url: `wss://127.0.0.1:${port}`, tlsFingerprint: response.tlsFingerprint } : null; } }; } //#endregion export { createConfiguredGatewayLocalProbe as t };