如何将HTTP代理与node.js http.Client一起使用?


137

我想使用standard从node.js发出传出HTTP调用http.Client。但是我无法直接从网络访问远程服务器,需要通过代理。

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


1
我有同样的问题。Node.js位于防火墙后面,我无法创建外部网站的HTTPClient。
ddallala 2010年

Answers:


152

关于使用HTTP代理,Tim Macfarlane答案很接近。

使用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/,但这是因为他们的服务器不在乎主机头是否正确。


1
有没有办法使用http代理连接https端口?似乎没有简单的方法
Gohan

@Gohan有关如何通过和http代理连接到https服务器的示例,请参见下面克里斯的答案。
HairOfTheDog

如果您收到错误的请求,请输入路径:'/'
Laurent Debricon

9
如何在选项块中集成代理用户和代理密码?
Twistleton 2014年

这改变了吗?即使最终目的地为另一本地服务器,我得到一个404,和目标服务器永远不会收到该请求..
OJFord

53

您可以使用request,我发现在node.js上使用代理非常简单,仅需一个外部“ proxy”参数,甚至可以通过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);
  }
})

1
工作了两个httphttps我的情况,非常感谢
萨穆埃尔补时

任何想法为什么这对于内部公司页面不起作用?
keinabel

1
我很惊讶内部公司页面在代理后面。您确定内部页面没有绕过代理吗?它在另一个VLAN上吗?
Chanoch

您需要以某种方式指定身份验证(如果我认为正确的话,会在此处发布)
Igor

使用代理请求时出现此错误:错误:无法建立隧道套接字,原因=连接ECONNREFUSED 127.0.0.1:80
Federico Caccia

35

我花了一段时间才弄清楚的一件事,即使您尝试通过https服务器进行代理,也可以使用“ http”访问代理。这对我使用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);
});

1
上面的代码对我不起作用,它与问题github.com/joyent/node/issues/2474相关,检查koichik的答案,我们必须使用“ method”:“ connect”,在“ connect”事件上,我们已经发送了路径信息。
Palani

16

正如@Renat在这里已经提到的,代理HTTP流量来自非常普通的HTTP请求。针对代理进行请求,并传递目标的完整URL作为路径。

var http = require ('http');

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

2
尽管Fiddler称它为协议违规,但这似乎不起作用,这表明它不是正确的HTTP request-via-proxy ...
Marc

11

以为我会添加我发现的这个模块:https : //www.npmjs.org/package/global-tunnel,这对我非常有用(立即使用我的所有代码和第三方模块,仅使用下面的代码)。

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

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

或者,调用

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

将使用http_proxy环境变量


2
这对我有用!实际上,通过这种方式,您可以将代理与代码分离,并将现有配置用于npm!我要说的就是这种方式
cesaregb 2015年

@NeelBasu是它
主要曼

9

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

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隧道。我在这里找到了解决方案。最终代码:

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()

7

“请求” http软件包似乎具有以下功能:

https://github.com/mikeal/request

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

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)
  }
})

不幸的是,没有“全局”默认值,因此使用该库的库用户无法修改代理,除非库通过http选项传递...

克里斯·HTH


request http包使您可以更轻松地使代码在代理和非代理使用之间切换(这在我的笔记本电脑上非常有用)。
乔恩·麦迪逊

5

基本上,您不需要显式的代理支持。代理协议非常简单,基于正常的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”。


3
不推荐使用http.createClient,Tim Macfarlane使用的是以下较新的http.get
萨米(

1
从v5.6开始,这显然不再适用于node.js,因为它们已经删除了createClient
Marc

5

如果您需要对代理提供者使用基本授权,则只需使用以下命令:

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();

1
在哪里可以找到“ FarmerAdapter”?
Alex

3

节点应支持使用http_proxy环境变量-因此它是跨平台的并且可以在系统设置上工作,而不需要按应用程序进行配置。

使用提供的解决方案,我将建议以下内容:

咖啡脚本

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

Java脚本

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"

在Windows上运行Node时,设置http_proxy似乎没有任何效果。
EricLaw 2014年

它应该在Windows(我正在使用的主要系统)下工作。设置完成后,请确保重置了终端会话(如果通过控制面板进行设置但未设置)。您应该可以使用echo%HTTP_PROXY%来检查其设置是否正确,甚至更好的是,您应该使用节点本身node -e“ console.log(process.env.http_proxy);” 这在Windows下对我有效,祝您好运。
路加福音

1

Imskull的答案几乎对我有用,但是我必须进行一些更改。唯一真正的更改是添加用户名,密码,并将拒绝未授权设置为false。我无法发表评论,所以我回答了这个问题。

如果运行代码,则可以按照以下教程获取有关Hacker News的最新故事的标题: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.');
    }
});

1

我认为,到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
});


0

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

根据该线程的答案,您似乎可以使用 代理通过代理服务器运行node.js:
$ proxychains /path/to/node application.js

我个人无法在Cygwin / Windows环境中安装任何代理链版本,因此无法对其进行测试。

此外,他们还讨论了使用connect-proxy的问题,但是我找不到有关如何执行此操作的任何文档。

简而言之,我仍然很困惑,但是也许有人可以使用此信息来找到合适的解决方法。


更新:经过一些调查后发现,由于不支持RTLD_NEXT,我无法在CygWin上构建代理链。
ddallala 2010年


0

像这样使用'https-proxy-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)=>{...});

0

如果您具有基本的 http身份验证方案,则必须输入base64字符串myuser:mypassword,然后在开头添加“ Basic”。这是Proxy-Authorization标头的值,下面是一个示例:

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中,您可以使用Buffer进行编码

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

console.log(encodedData);

举例来说,在浏览器中,您可以使用btoa()在base64中进行编码,这在浏览器中的ajax请求中很有用,而无需代理设置即可使用代理执行请求。

var encodedData = btoa('myuser:mypassword')

console.log(encodedData);

如何找到夹心方案接受代理服务器?

如果我们没有配置自定义DNS(会引发类似ERR_NAME_NOT_RESOLVED之类的错误),则当我们执行请求时,响应(代码407)应在响应头中告知代理正在使用哪种HTTP身份验证方案。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.