Node.js使用代理需要什么?
Node.js内置fetch基于undici库实现,默认不读取代理设置。因此HTTP代理需将undici的ProxyAgent作为dispatcher传递,SOCKS5代理需将socks-proxy-agent作为agent传递给Node的https模块。
示例使用IP 198.51.100.23,HTTP端口8000,SOCKS5端口1080,用户名spx_user,密码spx_pass。所有代码均为ES模块格式(.mjs)。
npm install undici socks-proxy-agent如何在 fetch 中连接 HTTP 代理?
ProxyAgent配置代理地址,用户名密码通过token选项以Basic认证格式传递。将undici导入的fetch与dispatcher结合使用,请求即通过代理转发。HTTPS地址会以CONNECT方式加密传输。
复用相同ProxyAgent可加快连接速度。为每个代理创建独立代理实例轮流使用即可。
import { fetch, ProxyAgent } from "undici";
const agent = new ProxyAgent({
uri: "http://198.51.100.23:8000",
token: "Basic " + Buffer.from("spx_user:spx_pass").toString("base64"),
});
const res = await fetch("https://api.ipify.org?format=json", { dispatcher: agent });
console.log(res.status, await res.json()); // "ip" should be the proxy IP如何连接SOCKS5代理?
socks-proxy-agent是与Node的http、https模块配合使用的代理工具。使用socks5h前缀时,域名解析将由代理服务器处理。下例演示如何将代理传递给https.get并收集响应内容。
像 axios 这样基于 http 模块运行的库,将相同的代理传递给 httpAgent 和 httpsAgent 即可使用 SOCKS5 发送请求。
import https from "node:https";
import { SocksProxyAgent } from "socks-proxy-agent";
const agent = new SocksProxyAgent("socks5h://spx_user:spx_pass@198.51.100.23:1080");
https.get("https://api.ipify.org?format=json", { agent }, (res) => {
let body = "";
res.on("data", (chunk) => (body += chunk));
res.on("end", () => console.log(res.statusCode, body));
}).on("error", (err) => console.error("request failed:", err.message));如何通过API获取列表并实现轮询?
启动时通过API获取代理列表并为每个代理创建代理器,每次请求时轮换使用。以下代码以ip:port:user:pass格式获取HTTP列表创建ProxyAgent数组,失败时自动切换至下一个代理重试。
请务必为请求设置AbortSignal.timeout超时。未响应请求堆积会导致整体任务延迟。
import { fetch, ProxyAgent } from "undici";
const API = "https://socks5proxy.io/api/v1";
const KEY = "YOUR_API_KEY";
const text = await (await fetch(API + "/proxies/download?format=ip:port:user:pass&protocol=http", {
headers: { Authorization: "Bearer " + KEY },
})).text();
const agents = text.trim().split("\n").map((line) => {
const [ip, port, user, pass] = line.trim().split(":");
return new ProxyAgent({
uri: "http://" + ip + ":" + port,
token: "Basic " + Buffer.from(user + ":" + pass).toString("base64"),
});
});
let i = 0;
async function get(url, tries = 3) {
for (let t = 0; t < tries; t++) {
const dispatcher = agents[i++ % agents.length];
try {
const res = await fetch(url, { dispatcher, signal: AbortSignal.timeout(20000) });
if (res.ok) return await res.text();
} catch {
// try the next proxy
}
}
return null;
}
console.log((await get("https://example.com/"))?.length);IP授权如何影响代码?
在控制台注册运行Node.js服务器的IPv4地址后,ProxyAgent只需使用地址无需token参数。SOCKS5也可直接使用socks5h://198.51.100.23:1080格式无需认证。避免密码暴露在环境变量或代码中,便于多服务器部署。
如果使用 axios,如何连接代理?
axios 基于 Node 的 http 和 https 模块运行,可通过传递代理使用代理。SOCKS5 需将 socks-proxy-agent 传递给 httpAgent 和 httpsAgent,并将 axios 自身的 proxy 选项设为 false,以避免设置冲突。
HTTP代理可通过axios的proxy选项设置host/port/auth,但对HTTPS地址使用agent更稳定。https-proxy-agent包可使HTTP代理采用相同结构连接。
import axios from "axios";
import { SocksProxyAgent } from "socks-proxy-agent";
const agent = new SocksProxyAgent("socks5h://spx_user:spx_pass@198.51.100.23:1080");
const client = axios.create({ httpAgent: agent, httpsAgent: agent, proxy: false, timeout: 20000 });
const { data } = await client.get("https://api.ipify.org?format=json");
console.log(data);同时发送多个请求时需要注意什么?
用Promise.all同时发起数千请求会导致连接数激增,给代理和目标站点造成压力。建议设置并发数限制,使用任务队列控制执行量,可用p-limit等包或自建简易函数实现。
均匀分配各代理的并发连接数可避免单IP过载。共享套餐包含500并发连接,请将总并发控制在此范围内。
能否通过环境变量全局应用代理设置?
undici的EnvHttpProxyAgent会读取HTTP_PROXY、HTTPS_PROXY和NO_PROXY环境变量设置代理。通过setGlobalDispatcher注册后,该进程的所有fetch请求都将经过代理。对于内部使用fetch的各类库,这可实现统一配置。
全局设置会使所有请求使用相同IP,更适合需要固定国家IP的工具或测试场景。若需轮换IP,请如前文所述通过dispatcher传递每个请求。
// HTTPS_PROXY=http://spx_user:spx_pass@198.51.100.23:8000 node app.mjs
import { EnvHttpProxyAgent, setGlobalDispatcher, fetch } from "undici";
setGlobalDispatcher(new EnvHttpProxyAgent());
const res = await fetch("https://api.ipify.org");
console.log(await res.text());常见问题如何解决?
若发现Node.js内置fetch似乎未应用dispatcher,请检查是否从undici包导入了fetch。内置fetch与安装的undici版本不一致可能导致代理不匹配,建议从同一包中获取fetch和ProxyAgent最可靠。
407响应表示认证信息错误。请检查token值中Basic后是否包含经base64编码的username:password组合。ECONNREFUSED通常是端口错误,HTTP代理需使用HTTP端口,SOCKS代理需使用SOCKS5端口。
- fetch和ProxyAgent同属undici包
- 407:检查token值与注册IP
- ECONNREFUSED: 区分HTTP端口与SOCKS5端口
- 全请求超时控制