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

+4 -1
View File
@@ -8,6 +8,7 @@ import { mkdir, readFile, rename, writeFile } from 'node:fs/promises';
import { dirname, join } from 'node:path';
import { RAW } from './sources.mjs';
import { MirrorPolicy } from './network.mjs';
import { guardDefaultFetch } from './env-proxy.mjs';
/**
* Read a cached JSON file, downloading it first when missing or unparsable.
@@ -26,6 +27,8 @@ import { MirrorPolicy } from './network.mjs';
* @returns {Promise<any>} parsed JSON
*/
export async function cachedJson({ cacheFile, url, refresh = false, offline = false, log = console.log, source = 'direct', proxyPrefix, fetchImpl = globalThis.fetch, mirrorPolicy, timeoutMs = 180000, backoffMs = 500 }) {
// Same rule as the file downloader: a configured proxy must not be skipped.
const fetchFn = guardDefaultFetch(fetchImpl);
if (!refresh || offline) {
try { return JSON.parse(await readFile(cacheFile, 'utf8')); } catch (e) {
if (offline) throw new Error(`--offline: cached index ${cacheFile} is missing or corrupt (${e.message}); run once online`);
@@ -40,7 +43,7 @@ export async function cachedJson({ cacheFile, url, refresh = false, offline = fa
let text, json;
try {
log(`[cache] downloading ${src}`);
const res = await network.request(src, fetchImpl, {}, timeoutMs);
const res = await network.request(src, fetchFn, {}, timeoutMs);
if (!res.ok) {
await res.body?.cancel();
if (res.status === 404 || res.status === 410) {