Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | 265x 265x 265x 265x 265x 140x 97x 97x 6x 6x 5x 1x 6x 44x 44x 37x 36x 9x 9x 9x 7x 265x 140x 140x 140x 140x 10x 10x 130x 34x 34x 36x 34x 34x 20x 20x 2x 18x 106x 106x | import * as fs from 'node:fs';
import type { Dispatcher } from 'undici';
import { GITLAB_CA_CERT_PATH, HTTP_PROXY, HTTPS_PROXY, NO_PROXY } from '../config';
import { logInfo, logWarn } from '../logger';
const undici = require('undici') as {
Agent: new (options: Record<string, unknown>) => unknown;
Pool: new (origin: string, options: Record<string, unknown>) => unknown;
EnvHttpProxyAgent: new (options: Record<string, unknown>) => Dispatcher;
};
interface NetworkOptions {
origin?: string;
insecureSkipVerify?: boolean;
connectTimeout: number;
headersTimeout: number;
bodyTimeout: number;
connections?: number;
keepAliveTimeout?: number;
keepAliveMaxTimeout?: number;
pipelining?: number;
}
let certificateLoaded = false;
let certificate: Buffer | undefined;
/** Load immutable process-level trust configuration once, before creating dispatchers. */
function loadCertificate(): Buffer | undefined {
if (certificateLoaded) return certificate;
certificateLoaded = true;
if (!GITLAB_CA_CERT_PATH) return undefined;
try {
certificate = fs.readFileSync(GITLAB_CA_CERT_PATH);
logInfo(`Custom CA certificate loaded from ${GITLAB_CA_CERT_PATH}`);
} catch (error: unknown) {
logWarn(`Failed to load CA certificate from ${GITLAB_CA_CERT_PATH}`, { err: error });
}
return certificate;
}
/** Remove proxy userinfo from diagnostics without altering connection configuration. */
function proxyUrlForLogging(value: string): string {
try {
const parsed = new URL(value);
if (!parsed.hostname) return '<invalid proxy URL>';
if (!parsed.username && !parsed.password) return value;
parsed.username = '';
parsed.password = '';
return parsed.toString();
} catch {
return '<invalid proxy URL>';
}
}
/** Share proxy routing, GitLab trust and timeouts between startup and instance transports. */
export function createNetworkDispatcher({
origin,
insecureSkipVerify,
connectTimeout,
...options
}: NetworkOptions): unknown {
const ca = loadCertificate();
const connect = {
...(insecureSkipVerify ? { rejectUnauthorized: false } : {}),
...(ca ? { ca } : {}),
timeout: connectTimeout,
keepAlive: true,
keepAliveInitialDelay: 30000,
};
const proxyUrl = (HTTPS_PROXY === '' ? undefined : HTTPS_PROXY) ?? HTTP_PROXY;
if (proxyUrl && /^(socks4?|socks5):\/\//.test(proxyUrl)) {
logInfo(`Using SOCKS proxy: ${proxyUrlForLogging(proxyUrl)}`);
logWarn('SOCKS proxy not supported with native fetch. Consider HTTP/HTTPS proxy.');
// SOCKS is unavailable; direct connections still retain GitLab trust and timeouts.
} else if (proxyUrl) {
logInfo(`Using proxy: ${proxyUrlForLogging(proxyUrl)}`);
// Undici's HTTP forwarding and CONNECT-client factories receive only connect options.
// Carry pool limits and response timeouts into those pools as well as target pools.
const factory = (poolOrigin: string | URL, poolOptions: Record<string, unknown>) =>
new undici.Pool(String(poolOrigin), { ...options, ...poolOptions });
const agent = new undici.EnvHttpProxyAgent({
...options,
httpProxy: HTTP_PROXY,
httpsProxy: HTTPS_PROXY,
noProxy: NO_PROXY,
factory,
clientFactory: factory,
connect,
requestTls: connect,
// Instance TLS overrides apply to GitLab, not the separate proxy trust boundary.
proxyTls: { timeout: connectTimeout },
});
if (!origin) return agent;
// Unlike a Pool, an Agent accepts arbitrary origins. Keep instance credentials
// confined to GitLab even when fetch follows redirects or NO_PROXY bypasses the proxy.
return agent.compose((dispatch) => (request, handler) => {
if (new URL(String(request.origin)).origin !== origin) {
throw new Error('Request origin does not match the configured GitLab instance');
}
return dispatch(request, handler);
});
}
const directOptions = { ...options, connect };
return origin ? new undici.Pool(origin, directOptions) : new undici.Agent(directOptions);
}
|