有一些npm软件包,用于在Node.js中设置全局http(s)代理。但是可以设置一个全球的socks5代理吗?
我首先深入the source code中的global-agent
,发现核心部分是这些行:
// Overriding globalAgent was added in v11.7.
// @see https://nodejs.org/uk/blog/release/v11.7.0/
if (semver.gte(process.version, 'v11.7.0')) {
// @see https://github.com/facebook/flow/issues/7670
// $FlowFixMe
http.globalAgent = httpAgent;
// $FlowFixMe
https.globalAgent = httpsAgent;
}
从v11.7版本开始,Node.js提供http.globalAgent
和https.globalAgent
用于全局修改来自http(s)模块的所有请求的代理。我想知道是否可以用袜子代理代替。因此,我尝试使用socks-proxy-agent
软件包,就像这样:
import http = require("http");
import https = require("https");
import SocksProxyAgent = require("socks-proxy-agent");
export function setSocksProxy(host: string, port: number) {
const proxyUrl = `socks://${host}:${port}`;
const agent = new SocksProxyAgent(proxyUrl);
http.globalAgent = https.globalAgent = agent;
}
事实证明:
1)在那些仅使用Node.js http(s)模块(在我的情况下为oauth
)的程序包中,它工作正常。
2)但是,在那些使用request
的软件包中,它失败了。错误消息是:
Error: a SOCKS proxy server `host` and `port` must be specified!
at new SocksProxyAgent (./node_modules/socks-proxy-agent/index.js:28:11)
at new ClientRequest (_http_client.js:116:13)
at TunnelingAgent.request (http.js:44:10)
at TunnelingAgent.createSocket (./node_modules/tunnel-agent/index.js:135:25)
at TunnelingAgent.createSecureSocket [as createSocket] (./node_modules/tunnel-agent/index.js:200:41)
at TunnelingAgent.createConnection (./node_modules/tunnel-agent/index.js:98:8)
at TunnelingAgent.addRequest (./node_modules/tunnel-agent/index.js:92:8)
at new ClientRequest (_http_client.js:277:16)
at Object.request (https.js:305:10)
at Object.request (./node_modules/agent-base/patch-core.js:23:20)
我遵循了调用堆栈,发现了一些东西。
在TunnelingAgent.createSocket
(./node_modules/tunnel-agent/index.js:135:25)中,connectOptions.agent
设置为false
。
var connectOptions = mergeOptions({}, self.proxyOptions,
{ method: 'CONNECT'
, path: options.host + ':' + options.port
, agent: false
}
)
var connectReq = self.request(connectOptions)
然后self.request(connectOptions)
呼叫http.request
。
在内部代码ClientRequest
(_http_client.js:116:13)中,由于options.agent
设置为false
,因此agent = new defaultAgent.constructor()
将运行。
let agent = options.agent;
const defaultAgent = options._defaultAgent || Agent.globalAgent;
if (agent === false) {
agent = new defaultAgent.constructor();
} else if (agent === null || agent === undefined) {
if (typeof options.createConnection !== 'function') {
agent = defaultAgent;
}
// Explicitly pass through this statement as agent will not be used
// when createConnection is provided.
} else if ...
this.agent = agent;
不幸的是,new SocksProxyAgent(proxyUrl)
需要一个参数。也就是说,我的先前的全局设置已丢失,因为http尝试创建一个新的SocksProxyAgent
(不带参数)。先前的代码:
const proxyUrl = `socks://${host}:${port}`;
const agent = new SocksProxyAgent(proxyUrl);
http.globalAgent = https.globalAgent = agent;
那么...我应该如何使它按理行事?