fix: align proxy routing across fetch and downloader

This commit is contained in:
Tam Nhu Tran
2026-03-16 07:10:39 -04:00
parent f50c9625de
commit fd5d16f3f3
5 changed files with 236 additions and 21 deletions
+10 -3
View File
@@ -5,9 +5,11 @@
* variables without routing CCS loopback traffic back through the proxy.
*/
import { Agent, Dispatcher, ProxyAgent, setGlobalDispatcher } from 'undici';
import { Agent, Dispatcher, ProxyAgent, fetch as undiciFetch, setGlobalDispatcher } from 'undici';
import { getProxyResolution, shouldBypassProxy } from './proxy-env';
const FETCH_PROXY_PROTOCOLS = ['http:', 'https:'];
type GlobalFetchProxyConfig = {
httpProxyUrl?: string;
httpsProxyUrl?: string;
@@ -133,6 +135,7 @@ export function applyGlobalFetchProxy(): { enabled: boolean; error?: string } {
}
setGlobalDispatcher(dispatcher);
globalThis.fetch = undiciFetch as typeof globalThis.fetch;
return { enabled: true };
} catch (error) {
const message = error instanceof Error ? error.message : 'Unknown proxy configuration error';
@@ -146,8 +149,12 @@ if (setupResult.error) {
}
function resolveGlobalFetchProxyConfig(): GlobalFetchProxyConfig {
const httpProxy = getProxyResolution(false);
const httpsProxy = getProxyResolution(true);
const httpProxy = getProxyResolution(false, process.env, {
allowedProtocols: FETCH_PROXY_PROTOCOLS,
});
const httpsProxy = getProxyResolution(true, process.env, {
allowedProtocols: FETCH_PROXY_PROTOCOLS,
});
return {
httpProxyUrl: httpProxy.url,
+10 -7
View File
@@ -1,7 +1,6 @@
type ProxyEnv = Record<string, string | undefined>;
type ProxyResolution = { url?: string; error?: string };
const SUPPORTED_PROXY_PROTOCOLS = new Set(['http:', 'https:']);
type ProxyResolutionOptions = { allowedProtocols?: string[] };
function getEnvValue(env: ProxyEnv, keys: string[]): string | undefined {
for (const key of keys) {
@@ -29,7 +28,7 @@ function isIpLikeHost(hostname: string): boolean {
return /^[\d.:]+$/.test(hostname);
}
function validateProxyUrl(proxyUrl: string): string {
function validateProxyUrl(proxyUrl: string, allowedProtocols?: string[]): string {
let parsedUrl: URL;
try {
parsedUrl = new URL(proxyUrl);
@@ -37,7 +36,7 @@ function validateProxyUrl(proxyUrl: string): string {
throw new Error('Invalid URL');
}
if (!SUPPORTED_PROXY_PROTOCOLS.has(parsedUrl.protocol)) {
if (allowedProtocols && !allowedProtocols.includes(parsedUrl.protocol)) {
throw new Error(`Unsupported proxy protocol: ${parsedUrl.protocol}`);
}
@@ -52,7 +51,11 @@ function getProxyKeys(isHttps: boolean): string[] {
return ['http_proxy', 'HTTP_PROXY', 'all_proxy', 'ALL_PROXY'];
}
export function getProxyResolution(isHttps: boolean, env: ProxyEnv = process.env): ProxyResolution {
export function getProxyResolution(
isHttps: boolean,
env: ProxyEnv = process.env,
options: ProxyResolutionOptions = {}
): ProxyResolution {
let firstError: string | undefined;
for (const key of getProxyKeys(isHttps)) {
@@ -62,7 +65,7 @@ export function getProxyResolution(isHttps: boolean, env: ProxyEnv = process.env
}
try {
return { url: validateProxyUrl(proxyUrl) };
return { url: validateProxyUrl(proxyUrl, options.allowedProtocols) };
} catch (error) {
if (!firstError) {
firstError = error instanceof Error ? error.message : 'Unknown proxy configuration error';
@@ -131,7 +134,7 @@ export function shouldBypassProxy(hostname: string, env: ProxyEnv = process.env)
const canonicalPattern = pattern.startsWith('.')
? pattern.slice(1)
: pattern.replace(/^\*/, '');
: pattern.replace(/^\*\.?/, '');
if (!canonicalPattern) {
continue;