JavaScript 语言发起 HTTP 代理请求代码示例

发布于 2026-02-07 | 作者: FreeProxy Team

很多开发者第一次尝试 JavaScript HTTP 代理请求时都会碰壁:fetch 与 XMLHttpRequest 的配置项里根本没有 proxy 参数。这不是疏漏,而是浏览器安全模型的刻意设计——页面里的脚本无权决定自己的网络出口。想让代理真正生效,必须先分清运行环境:浏览器端依靠系统代理、扩展或启动参数,Node.js 端则可以自由配置代理。本文把两条路线一次讲清,并给出可运行的佐证示例。

浏览器端为什么无法直接设置代理

浏览器的网络栈由浏览器本体掌控,页面脚本只能发起请求,不能指定出口节点。系统或浏览器设置里的代理与 PAC 脚本对所有页面统一生效,fetch 没有任何参数可以覆盖它。扩展程序则不同:Chrome 为扩展提供了 WebRequest 与 proxy 等特权 API,允许扩展改写代理规则,这正是 SwitchyOmega 这类代理切换扩展的实现原理。

浏览器场景的替代方案

既然页面代码里配不了代理,就应把配置动作上移到更合适的层级,按场景选择:

  • 代理扩展:安装 SwitchyOmega 等扩展,按域名规则切换代理,适合人工调试。
  • 启动参数:Chrome 追加 --proxy-server=http://127.0.0.1:8080,常配合自动化框架使用。
  • 服务端转发:浏览器只请求自己的后端接口,由后端携带代理转发,页面对代理无感知。
  • 系统代理:直接在操作系统层面配置,影响全部流量,粒度最粗但最省事。

Node.js 环境下的代理请求原理

Node.js 没有浏览器沙箱的限制,http 模块原生就能与正向代理对话:向代理端口发送请求,但把请求行里的路径写成完整的目标 URL(绝对形式),并用 Host 头声明真实主机,代理即可据此转发。下面这段代码保存为 proxy.js 后可直接运行:

const http = require('http');

// 向正向代理发起请求:path 使用完整的绝对 URL,Host 头声明真实目标
const req = http.request({
  host: '127.0.0.1',               // 代理服务器地址
  port: 8080,                       // 代理端口
  path: 'http://httpbin.org/ip',    // 绝对形式的目标地址
  method: 'GET',
  headers: { Host: 'httpbin.org' },
  timeout: 10000
}, (res) => {
  let body = '';
  res.setEncoding('utf8');
  res.on('data', (chunk) => { body += chunk; });
  res.on('end', () => console.log('状态码:', res.statusCode, body));
});

req.on('timeout', () => req.destroy(new Error('请求超时')));
req.on('error', (err) => console.error('请求失败:', err.message));
req.end();

返回 200 说明代理链路正常;若代理要求认证,在 headers 里补充 Proxy-Authorization 即可。注意这种绝对形式只适用于 http 协议的目标,https 目标需要 CONNECT 隧道配合 TLS 握手,我们在 NodeJS 原生实现一文中专门展开。

自动化测试中给浏览器挂代理

Puppeteer、Playwright 等框架的本质是驱动一个受控浏览器,因此配置代理要使用浏览器启动参数而不是页面脚本。以 Puppeteer 为例:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
    headless: true,
    args: ['--proxy-server=http://127.0.0.1:8080']
  });

  const page = await browser.newPage();
  await page.authenticate({ username: 'user', password: 'pass' });
  await page.goto('https://httpbin.org/ip');
  console.log(await page.content());

  await browser.close();
})();

page.authenticate 会在代理弹出认证框时自动应答,等价于人工输入账号密码,比把凭据拼进 URL 更安全。

注意事项与常见误区

  • 不存在 fetch 代理参数:任何声称给前端 fetch 传 proxy 的写法都不会生效,请勿采信。
  • 代理凭据不进前端:写在页面里的账号密码等于公开信息,认证逻辑应放在服务端。
  • CORS 依旧存在:换代理不会改变同源策略,跨域问题仍需后端或网关配合。
  • 环境变量只对 Node 生效:HTTP_PROXY 影响的是服务端请求,浏览器并不读取它。

Article ID: 32

(本文仅供技术交流,请遵守法律法规)

返回知识库
广告区域 (Ad Space)