UNPKG

@codacy/codacy-mcp

Version:

Codacy MCP server

75 lines (74 loc) 3.58 kB
import { Agent, ProxyAgent, setGlobalDispatcher } from 'undici'; // Matches a request hostname against the NO_PROXY / no_proxy list. // Handles exact matches and suffix matches (e.g. "example.com" also covers "sub.example.com"). function matchesNoProxy(hostname) { const noProxy = process.env.NO_PROXY ?? process.env.no_proxy; if (!noProxy) return false; const lower = hostname.toLowerCase(); return noProxy .split(',') .map(h => h.trim().toLowerCase().replace(/^\./, '')) .filter(Boolean) .some(entry => entry === '*' || lower === entry || lower.endsWith('.' + entry)); } // Ensures a proxy URL has a protocol prefix. A bare host:port (e.g. "localhost:8080") // is treated as HTTP, matching the convention used by curl and most proxy tools. function normalizeProxyUrl(url) { return /^https?:\/\//i.test(url) ? url : `http://${url}`; } // Routes each fetch() call through HTTPS_PROXY or HTTP_PROXY based on the request // protocol, bypassing the proxy for any host that matches NO_PROXY. // Extends Agent so all Dispatcher methods are already implemented. class ProxyRoutingDispatcher extends Agent { _httpsProxy; _httpProxy; constructor(httpProxy, httpsProxy, disableSSL) { super(); // requestTls — TLS to the target server through the CONNECT tunnel. // proxyTls — TLS to the proxy itself (relevant when proxy URL is HTTPS). const tlsOpts = disableSSL ? { rejectUnauthorized: false } : undefined; const proxyOpts = tlsOpts ? { requestTls: tlsOpts, proxyTls: tlsOpts } : {}; this._httpsProxy = httpsProxy ? new ProxyAgent({ uri: normalizeProxyUrl(httpsProxy), ...proxyOpts }) : undefined; this._httpProxy = httpProxy ? new ProxyAgent({ uri: normalizeProxyUrl(httpProxy), ...proxyOpts }) : undefined; } dispatch(options, handler) { const origin = options.origin instanceof URL ? options.origin : new URL(String(options.origin)); if (!matchesNoProxy(origin.hostname)) { const proxy = origin.protocol === 'https:' ? (this._httpsProxy ?? this._httpProxy) : (this._httpProxy ?? this._httpsProxy); if (proxy) return proxy.dispatch(options, handler); } return super.dispatch(options, handler); } } /** * Reads proxy configuration from environment variables and patches the global * fetch dispatcher used by Node.js native fetch. * * Supported env vars: * HTTPS_PROXY / https_proxy — proxy for HTTPS requests * HTTP_PROXY / http_proxy — proxy for HTTP requests * NO_PROXY / no_proxy — comma-separated list of hosts to bypass * NODE_TLS_REJECT_UNAUTHORIZED=0 — disable TLS certificate verification * * For corporate environments that use SSL inspection (MITM proxies), prefer adding the * corporate CA certificate to Node's trust store rather than disabling verification: * NODE_EXTRA_CA_CERTS=/path/to/corporate-ca.pem * Node reads this at startup and it applies to all TLS connections, including * the inner tunnel established through a CONNECT proxy. */ export function applyProxyConfig() { const httpsProxy = process.env.HTTPS_PROXY ?? process.env.https_proxy; const httpProxy = process.env.HTTP_PROXY ?? process.env.http_proxy; if (!httpsProxy && !httpProxy) return; const disableSSL = process.env.NODE_TLS_REJECT_UNAUTHORIZED === '0'; setGlobalDispatcher(new ProxyRoutingDispatcher(httpProxy, httpsProxy, disableSSL)); }