feedback7 G-TOOLS: asset downloads honour HTTP(S)_PROXY on Node 22.21+ and 24 (PR #289 by @weinibuliu)

Did not apply the patch. It set a global dispatcher on the npm undici package and rewrote the lockfile. Node's built-in fetch does not use that dispatcher, and node:undici is not importable. fetch() reads HTTP_PROXY, HTTPS_PROXY and NO_PROXY only at startup, and only when that startup had NODE_USE_ENV_PROXY=1 (or --use-env-proxy). That is Node >=22.21.0 and >=24.0.0.

tools/fetch-assets.mjs restarts itself once with NODE_USE_ENV_PROXY=1 before downloading. The default fetch in the downloader and the index cache rejects when a proxy is set but this process cannot use it, including Node 22.0–22.20 and 23, instead of fetching directly. No new dependency. Engines stay >=22.

Tests: node --test test/assets-env-proxy.test.js — 8 pass, 0 fail. node --test test/asset-network.test.js test/assets-diy.test.js test/fetch-assets-shrink.test.js test/assets.test.js — 84 pass, 0 fail. Before this commit: npm run -s lint — 0 errors (135 existing warnings); npm run -s typecheck — ok; npm run -s check:imports — exit 0 (3 pre-existing sim-node notes). docs, version and package tests: 46 pass and 1 fail while env-proxy.mjs was still untracked; after git add, node --test test/package.test.js — 10 pass, 0 fail.
This commit is contained in:
weinibuliu authored and sganggs committed 2026-10-08 19:07:49 +08:00
1 parent 51c53de189
commit b5c29b5335
5 files changed
+463 -3

No files matched your search

+5 -1
View File
@@ -8,6 +8,9 @@
// a 404/410 moves on immediately. Each candidate uses its opt-in prefix proxy
// first (when enabled), then the original URL and jsDelivr fallback. The proxy gets one short attempt
// per file and shares a run-wide circuit breaker with the index/font fetchers.
// - HTTP(S)_PROXY: the default fetch uses it only when this process was started
// with NODE_USE_ENV_PROXY=1 (Node >=22.21 or >=24). Otherwise it fails closed
// (tools/assets/env-proxy.mjs). Pass fetchImpl to bypass that, as tests do.
// - Idempotent: an existing file is kept when its size matches the ledger entry
// of a previous download or the expected byte count from research, or (when
// neither is known) when it passes format validation. The ledger lives in
@@ -18,6 +21,7 @@ import { mkdir, readFile, rename, stat, unlink, writeFile } from 'node:fs/promis
import { dirname, join } from 'node:path';
import { MirrorPolicy } from './network.mjs';
import { validate } from './formats.mjs';
import { guardDefaultFetch } from './env-proxy.mjs';
/**
* @typedef {{ rel: string, urls: string[], kind: string, bytes?: number, mutable?: boolean }} Job
@@ -60,7 +64,7 @@ export class Downloader {
/** @type {Set<string>} the files (paths under root) this run wrote */
this.written = new Set();
this.log = log;
this.fetch = fetchImpl;
this.fetch = guardDefaultFetch(fetchImpl);
this.network = mirrorPolicy ?? new MirrorPolicy({ source, proxyPrefix, log });
this.backoffMs = Math.max(0, Number(backoffMs) || 0);
this.ledger = { files: {} };