集成阅读约 4 分钟

在 Node.js fetch 中使用代理

让 Node.js 原生 fetch 经由 Undici ProxyAgent 走代理,并配置显式的代理认证、中止期限和响应体清理。

本页内容

起点

为单次 fetch 调用使用一个 dispatcher,使代理配置显式化,进程中的其他网络客户端则保留各自的配置。

选择兼容的运行时与 dispatcher

这个服务端示例面向 Node.js 24 和 Undici 7。在一个单独的示例项目中运行 npm install undici@7。Node 内置的 fetch 接受与 Undici 兼容的 dispatcher。这与浏览器中的 fetch 不同,页面 JavaScript 无法任意选择系统代理。

在 PROXY_URL 中使用提供商文档给出的 HTTP(S) 网关,例如刻意无法工作的 https://proxy.example.invalid:8443。通过部署环境的密钥管理器注入 PROXY_USERNAME 和 PROXY_PASSWORD。不要把网关凭据放进前端代码。

把代理认证放在 dispatcher 上

保存为 proxy-check.mjs 并运行 node proxy-check.mjs。Basic 令牌属于代理 agent,而不是目标站点的 Authorization 请求头。该请求有 30 秒的中止期限,并且不会自动跟随重定向。

proxy-check.mjs · Node.js 24 + Undici 7

javascript
import { ProxyAgent } from 'undici';

function required(name) {
  const value = process.env[name];
  if (!value) throw new Error('Missing environment variable: ' + name);
  return value;
}

const gateway = new URL(required('PROXY_URL'));
if (!['http:', 'https:'].includes(gateway.protocol) || gateway.username || gateway.password) {
  throw new Error('Use a credential-free HTTP(S) proxy URL');
}
const credentials = required('PROXY_USERNAME') + ':' + required('PROXY_PASSWORD');
const dispatcher = new ProxyAgent({
  uri: gateway.href,
  token: 'Basic ' + Buffer.from(credentials).toString('base64'),
});

try {
  const response = await fetch('https://example.com/', {
    dispatcher,
    signal: AbortSignal.timeout(30_000),
    redirect: 'manual',
  });
  await response.body?.cancel();
  if (!response.ok) throw new Error('Destination HTTP ' + response.status);
  console.log({ status: response.status });
} finally {
  await dispatcher.close();
}

从诊断脚本走向工作进程

这个脚本刻意取消了响应体,因为诊断只需要状态码。使用结果的工作进程应在其预算内消费响应体。在继续之前务必消费或取消它,并在工作进程关闭时关闭 dispatcher。

对于重复的任务,复用一个并发受限的 dispatcher,而不是为每个请求创建一个。让每个任务的期限彼此独立。除非有意改变每个受影响客户端的路由,否则不要安装进程级的 dispatcher。

  • HTTP 错误是一个响应;fetch 不会仅仅因为状态码是 4xx 或 5xx 而 reject。
  • CONNECT 被拒绝可能在目标站点的 Response 存在之前就表现为 fetch 失败。
  • 记录脱敏后的错误类别;不要记录 Basic 令牌或包含凭据的完整 URL。

上线之前

  • 使用文档中给出的 Node 和 Undici 主版本。
  • 显式传入 dispatcher。
  • 消费或取消响应体,并关闭 agent。

参考来源与延伸阅读

本指南参考的技术资料。请以你所安装版本的文档以及代理服务商支持的配置为准。