让 Node HTTP 经过代理的请求行
用 Node 的核心客户端构造普通 HTTP 代理请求,把连接端点、绝对目标和 Host 头分开处理。
对于经过正向代理的普通 HTTP 请求,Node 连接到代理,并把目标 URL 写进请求行。三个值描述这同一个请求:
| 值 | 示例 |
|---|---|
| TCP 连接端点 | proxy.example:8080 |
| 请求目标 | http://example.com/news?q=proxy |
| Host 头 | example.com |
这个 Node 22 示例把这种分离写得很清楚:
const http = require('node:http');
const destination = new URL('http://example.com/news?q=proxy');
const request = http.get({
hostname: 'proxy.example',
port: 8080,
path: destination.href,
headers: { Host: destination.host },
signal: AbortSignal.timeout(15000),
}, (response) => {
console.log(response.statusCode);
response.on('error', console.error);
response.resume();
});
request.on('error', console.error);
端点是占位符;要做一次公开的 HTTP 测试,可以从HTTP 代理列表里挑一个候选,并检查它的响应。示例在打印状态码后把响应读空;应用程序也可以改为消费正文。查询串仍然是请求目标的一部分。
为什么完整 URL 要放在那里
源服务器通常收到的是 /news?q=proxy 这样的目标。正向代理也需要知道目的地,因此 HTTP/1.1 定义了绝对形式的请求目标:
GET http://example.com/news?q=proxy HTTP/1.1
Host: example.com
按照 HTTP/1.1 的规则,收到绝对形式的代理在转发时使用 URI 的授权部分,并替换掉不一致的接收到的 Host 字段。发送一致的 Host 头仍能让发出的请求保持无歧义。Node 的连接主机名只是中间跳,所以要显式设置这个头,而不是依赖连接地址。
如果需要认证,代理的凭据属于它自己这一跳。Node 的 auth 请求选项会为资源生成 Authorization 头;它并不是通用的代理登录选项。当交互更复杂时,请使用代理要求的方案和合适的代理客户端。
HTTPS 还要加一条隧道
这个示例只覆盖普通 HTTP 转发。典型的通过 HTTP 代理的 HTTPS 连接会先请求 CONNECT example.com:443,然后在已接受的隧道里向目标启动 TLS。把示例 URL 改成 HTTPS 并不会自动增加这些阶段。
对于 HTTPS 或混合负载,请使用具备所需隧道支持的、仍在维护的代理 agent 或 dispatcher。对于兼容的 Node 版本,一个选择是带 ProxyAgent 的 Undici fetch。当你需要控制或理解的正是普通 HTTP 交互本身时,就保留这个小巧的核心客户端示例。