如何在 node.jshttp. Client 中使用 http 代理?

我想使用标准的 http.Client从 node.js 发出 HTTP 调用。但是我不能直接从我的网络到达远程服务器,需要通过一个代理。

如何告诉 node.js 使用代理?

277093 次浏览

可能不是你所希望的那种一行程序,但是你可以看看 http://github.com/nodejitsu/node-http-proxy,因为它可能会让你了解如何使用你的应用程序与 http。客户。

基本上,您不需要显式的代理支持。代理协议非常简单,基于普通的 HTTP 协议。在连接 HTTPClient 时,您只需使用代理主机和端口。示例(来自 node.js 文档) :

var http = require('http');
var google = http.createClient(3128, 'your.proxy.host');
var request = google.request('GET', '/',
{'host': 'www.google.com'});
request.end();
...

所以基本上你连接到你的代理服务器,但是请求“ http://www.google.com”。

Http://groups.google.com/group/nodejs/browse_thread/thread/d5aadbcaa00c3f7/12ebf01d7ec415c3?lnk=gst&q=proxy#12ebf01d7ec415c3

根据这个线程给出的答案,似乎可以使用 < a href = “ http://proxychains.sourceforge.net/”rel = “ nofollow”> proxychain 通过代理服务器运行 node.js:
$ proxychains /path/to/node application.js

就个人而言,我无法在 Cygwin/Windows环境中安装任何 代理链版本,因此无法测试它。

此外,他们还谈到了使用 连接代理服务器,但是我找不到任何关于如何做到这一点的文档。

简而言之,我仍然卡住了,但是也许有人可以利用这些信息来找到一个合适的解决办法。

正如@Renat 在这里已经提到的,代理 HTTP 流量来自非常普通的 HTTP 请求。对代理发出请求,将目标的 完整网址作为路径传递。

var http = require ('http');


http.get ({
host: 'my.proxy.com',
port: 8080,
path: 'http://nodejs.org/'
}, function (response) {
console.log (response);
});

我花了一段时间才弄明白的一件事是,使用“ http”访问代理,即使您试图通过代理访问 https 服务器。使用 Charles (osx 协议分析器)我可以做到这一点:

var http = require('http');


http.get ({
host: '127.0.0.1',
port: 8888,
path: 'https://www.google.com/accounts/OAuthGetRequestToken'
}, function (response) {
console.log (response);
});

Tim Macfarlane 的 回答在使用 HTTP 代理方面非常接近。

使用 HTTP 代理(对于不安全的请求)非常简单。除了路径部分包含完整的 URL 和主机头被设置为您想要连接到的主机之外,您可以连接到代理并正常地发出请求。
蒂姆的回答非常接近,但是他错过了正确设置主持人的头球。

var http = require("http");


var options = {
host: "proxy",
port: 8080,
path: "http://www.google.com",
headers: {
Host: "www.google.com"
}
};
http.get(options, function(res) {
console.log(res);
res.pipe(process.stdout);
});

根据记录,他的答案确实适用于 http://nodejs.org/,但那是因为他们的服务器不关心主机头是不正确的。

“请求”http 包似乎有这样一个特性:

Https://github.com/mikeal/request

例如,下面的“ r”请求对象使用 localxy 访问它的请求:

var r = request.defaults({'proxy':'http://localproxy.com'})


http.createServer(function (req, resp) {
if (req.url === '/doodle.png') {
r.get('http://google.com/doodle.png').pipe(resp)
}
})

不幸的是,没有“全局”默认值,因此使用这个默认值的 lib 用户不能修改代理,除非 lib 通过 http 选项..。

嗨,克里斯

节点应该支持使用 http _ agent 环境变量——因此它是跨平台的,可以在系统设置上工作,而不需要针对每个应用程序进行配置。

使用提供的解决方案,我建议采用以下方法:

咖啡稿

get_url = (url, response) ->
if process.env.http_proxy?
match = process.env.http_proxy.match /^(http:\/\/)?([^:\/]+)(:([0-9]+))?/i
if match
http.get { host: match[2], port: (if match[4]? then match[4] else 80), path: url }, response
return
http.get url, response

Javascript

get_url = function(url, response) {
var match;
if (process.env.http_proxy != null) {
match = process.env.http_proxy.match(/^(http:\/\/)?([^:\/]+)(:([0-9]+))?/i);
if (match) {
http.get({
host: match[2],
port: (match[4] != null ? match[4] : 80),
path: url
}, response);
return;
}
}
return http.get(url, response);
};

用法 要使用这个方法,只需要有效地替换 http.get,例如,下面将 google 的索引页写入一个名为 test.htm 的文件:

file = fs.createWriteStream path.resolve(__dirname, "test.htm")
get_url "http://www.google.com.au/", (response) ->
response.pipe file
response.on "end", ->
console.log "complete"

截至2020年2月11日,请求已被完全废弃,预计不会有新的变化。

你可以用 请求, 我只是发现在 node.js 上使用代理简直难以置信的简单,只需要一个外部的“代理”参数,它甚至通过一个 http 代理支持 HTTPS。

var request = require('request');


request({
'url':'https://anysite.you.want/sub/sub',
'method': "GET",
'proxy':'http://yourproxy:8087'
},function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
}
})

我想我会添加这个模块,我发现: https://www.npmjs.org/package/global-tunnel,这对我来说非常好(工作立即与我的所有代码和第三方模块,只有下面的代码)。

require('global-tunnel').initialize({
host: '10.0.0.10',
port: 8080
});

这样做一次,应用程序中的所有 http (和 https)都将通过代理。

轮流打电话

require('global-tunnel').initialize();

将使用 ABc0环境变量

如果你需要为你的代理服务提供商使用基本授权,只需使用以下方法:

var http = require("http");


var options = {
host:       FarmerAdapter.PROXY_HOST,
port:       FarmerAdapter.PROXY_PORT,
path:       requestedUrl,
headers:    {
'Proxy-Authorization':  'Basic ' + new Buffer(FarmerAdapter.PROXY_USER + ':' + FarmerAdapter.PROXY_PASS).toString('base64')
}
};


var request = http.request(options, function(response) {
var chunks = [];
response.on('data', function(chunk) {
chunks.push(chunk);
});
response.on('end', function() {
console.log('Response', Buffer.concat(chunks).toString());
});
});


request.on('error', function(error) {
console.log(error.message);
});


request.end();

伊姆库克的回答对我来说几乎奏效了,但我不得不做出一些改变。唯一真正的变化是添加用户名、密码和设置 rejectUnauthority 为 false。我不能发表评论,所以我把这个作为回答。

如果你运行这个代码,它会给你黑客新闻上当前故事的标题,这个教程是: http://smalljs.org/package-managers/npm/

var cheerio = require('cheerio');
var request = require('request');


request({
'url': 'https://news.ycombinator.com/',
'proxy': 'http://Username:Password@YourProxy:Port/',
'rejectUnauthorized': false
}, function(error, response, body) {
if (!error && response.statusCode == 200) {
if (response.body) {
var $ = cheerio.load(response.body);
$('td.title a').each(function() {
console.log($(this).text());
});
}
} else {
console.log('Error or status not equal 200.');
}
});

像这样使用「 https-xy-agent 」

var HttpsProxyAgent = require('https-proxy-agent');
var proxy = process.env.https_proxy || 'other proxy address';
var agent = new HttpsProxyAgent(proxy);


options = {
//...
agent : agent
}


https.get(options, (res)=>{...});

我买了私人代理服务器,购买后我得到:

255.255.255.255 // IP address of proxy server
99999 // port of proxy server
username // authentication username of proxy server
password // authentication password of proxy server

我想利用这一点。第一个回答第二个答案只适用于 http (代理)-> http (目的地) ,但是我想要 http (代理)-> https (目的地)。

对于 https 目的地,最好直接使用 HTTP 隧道。 我找到了解决方案 给你

节点 v8:

const http = require('http')
const https = require('https')
const username = 'username'
const password = 'password'
const auth = 'Basic ' + Buffer.from(username + ':' + password).toString('base64')


http.request({
host: '255.255.255.255', // IP address of proxy server
port: 99999, // port of proxy server
method: 'CONNECT',
path: 'kinopoisk.ru:443', // some destination, add 443 port for https!
headers: {
'Proxy-Authorization': auth
},
}).on('connect', (res, socket) => {
if (res.statusCode === 200) { // connected to proxy server
https.get({
host: 'www.kinopoisk.ru',
socket: socket,    // using a tunnel
agent: false,      // cannot use a default agent
path: '/your/url'  // specify path to get from server
}, (res) => {
let chunks = []
res.on('data', chunk => chunks.push(chunk))
res.on('end', () => {
console.log('DONE', Buffer.concat(chunks).toString('utf8'))
})
})
}
}).on('error', (err) => {
console.error('error', err)
}).end()

节点 v14:

const http = require('http');
const https = require('https');
const username = 'username';
const password = 'password';
const auth = 'Basic ' + Buffer.from(username + ':' + password).toString('base64');


http.request({
host: '255.255.255.255', // IP address of proxy server
port: 99999, // port of proxy server
method: 'CONNECT',
path: 'kinopoisk.ru:443', // some destination, add 443 port for https!
headers: {
'Proxy-Authorization': auth
},
}).on('connect', (res, socket) => {
if (res.statusCode === 200) { // connected to proxy server
const agent = new https.Agent({ socket });
https.get({
host: 'www.kinopoisk.ru',
path: '/',
agent,      // cannot use a default agent
}, (res) => {
let chunks = []
res.on('data', chunk => chunks.push(chunk))
res.on('end', () => {
console.log('DONE', Buffer.concat(chunks).toString('utf8'))
})
})
}
}).on('error', (err) => {
console.error('error', err)
}).end();

如果您有 基本 http 认证方案,那么您必须创建一个 myuser:mypassword的 base64字符串,然后在开头添加“ Basic”。这是 代理-授权头部的值,这里有一个例子:

var Http = require('http');


var req = Http.request({
host: 'myproxy.com.zx',
port: 8080,
headers:{"Proxy-Authorization": "Basic bXl1c2VyOm15cGFzc3dvcmQ="},
method: 'GET',
path: 'http://www.google.com/'
}, function (res) {
res.on('data', function (data) {
console.log(data.toString());
});
});


req.end();

在 nodejs 中,可以使用 缓冲器进行编码

var encodedData = Buffer.from('myuser:mypassword').toString('base64');


console.log(encodedData);

例如,在浏览器中,您可以使用 (德语)在 base64中进行编码,这在浏览器中的 ajax 请求中非常有用,不需要使用代理执行请求的代理设置。

var encodedData = btoa('myuser:mypassword')


console.log(encodedData);

如何查找 Wich 方案接受代理服务器

如果我们没有配置自定义 DNS (这将抛出类似 ERR _ NAME _ NOT _ RESOLVED 的东西) ,当我们执行一个请求时,响应(代码407)应该在响应头中告知代理正在使用的 http 认证方案。

我认为在2019年有一个更好的选择。我们可以使用 global-tunnel-ng包初始化代理,而不会污染到处的基于 httphttps的代码。因此,首先安装 global-tunnel-ng软件包:

npm install global-tunnel-ng

然后根据需要更改实现以初始化代理:

const globalTunnel = require('global-tunnel-ng');


globalTunnel.initialize({
host: 'proxy.host.name.or.ip',
port: 8080
});

只要设定环境变量,abc0就会使用代理服务器。

const env = {
"host": "proxy.server.com.br",
"port": 8080,
"user": "my-user",
"pass": "my-pass"
};


process.env.http_proxy =
process.env.https_proxy =
`http://${env.user}:${env.pass}@${env.host}:${env.port}/`;

Axios 在其 文件中有代理选项。 还可以定义 http_proxyhttps_proxy环境变量

// `proxy` defines the hostname, port, and protocol of the proxy server.
// You can also define your proxy using the conventional `http_proxy` and
// `https_proxy` environment variables. If you are using environment variables
// for your proxy configuration, you can also define a `no_proxy` environment
// variable as a comma-separated list of domains that should not be proxied.
// Use `false` to disable proxies, ignoring environment variables.
// `auth` indicates that HTTP Basic auth should be used to connect to the proxy, and
// supplies credentials.
// This will set an `Proxy-Authorization` header, overwriting any existing
// `Proxy-Authorization` custom headers you have set using `headers`.
// If the proxy server uses HTTPS, then you must set the protocol to `https`.


proxy: {
protocol: 'https',
host: '127.0.0.1',
port: 9000,
auth: {
username: 'mikeymike',
password: 'rapunz3l'
}
},