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

时间:2010-10-05 10:32:54

标签: http proxy node.js

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

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

18 个答案:

答案 0 :(得分:138)

关于使用HTTP代理,

Tim Macfarlaneanswer已接近。

使用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 :(得分:46)

您可以使用request, 我发现在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);
  }
})

答案 2 :(得分:31)

有一件事花了我一段时间才弄清楚,使用'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);
});

答案 3 :(得分:15)

正如@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);
});

答案 4 :(得分: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环境变量

答案 5 :(得分:7)

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

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

HTH,Chris

答案 6 :(得分:5)

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

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”。

答案 7 :(得分:4)

如果您需要使用代理提供商的基本授权,请使用以下命令:

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

答案 8 :(得分:3)

Node应该支持使用http_proxy环境变量 - 因此它是跨平台的,可以在系统设置上工作,而不需要每个应用程序配置。

使用提供的解决方案,我建议如下:

<强>的CoffeeScript

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"

答案 9 :(得分:3)

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

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

我想用它。 First answersecond answer仅适用于http(代理) - &gt; http(目的地),但我想要http(代理) - &gt; HTTPS(目的地)。

对于https目标,最好直接使用HTTP tunnel。 我找到了解决方案here。最终代码:

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

答案 10 :(得分:1)

Imskull的回答几乎对我有用,但我不得不做出一些改变。唯一真正的变化是添加用户名,密码,并将rejectUnauthorized设置为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.');
    }
});

答案 11 :(得分:0)

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

基于此主题的答案,您似乎可以使用proxychains 通过代理服务器运行node.js:
$ proxychains /path/to/node application.js

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

此外,他们还谈到了使用 connect-proxy ,但我找不到任何关于如何执行此操作的文档。

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

答案 12 :(得分:0)

可能不是您希望的确切单行,但您可以查看http://github.com/nodejitsu/node-http-proxy,因为这可能会为您如何在http.Client中使用您的应用提供一些启示。

答案 13 :(得分:0)

对于使用https的代理我尝试了这个网站上的建议(使用依赖 https-proxy-agent ),它对我有用:

http://codingmiles.com/node-js-making-https-request-via-proxy/

答案 14 :(得分:0)

使用&#39; https-proxy-agent&#39;像这样

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)=>{...});

答案 15 :(得分:0)

如果你有Basic http authentication scheme,你必须创建一个{64}的base64字符串,然后在开头添加“Basic”。这是Proxy-Authorization标题的值,这里是一个例子:

myuser:mypassword

在nodejs中,您可以使用Buffer进行编码

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

就像示例一样,在浏览器中,您可以使用btoa()在base64中编码,在浏览器中的ajax请求中很有用,而不使用代理执行请求的代理设置。

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

console.log(encodedData);

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

如果我们没有配置自定义DNS(会抛出类似ERR_NAME_NOT_RESOLVED的东西),当我们执行请求时,响应(代码407)应该在响应头中通知代理正在使用的http身份验证方案。 / p>

答案 16 :(得分:0)

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

答案 17 :(得分:0)