简体   繁体   English

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

[英]How can I use an http proxy with node.js http.Client?

I want to make an outgoing HTTP call from node.js, using the standard http.Client .我想使用标准的http.Client从 node.js 进行传出 HTTP 调用。 But I cannot reach the remote server directly from my network and need to go through a proxy.但是我无法直接从我的网络访问远程服务器,需要通过代理。

How do I tell node.js to use the proxy?我如何告诉 node.js 使用代理?

Tim Macfarlane 's answer was close with regards to using a HTTP proxy.关于使用 HTTP 代理, Tim Macfarlane回答很接近。

Using a HTTP proxy (for non secure requests) is very simple.使用 HTTP 代理(用于非安全请求)非常简单。 You connect to the proxy and make the request normally except that the path part includes the full url and the host header is set to the host you want to connect to.您连接到代理并正常发出请求,只是路径部分包含完整的 url 并且主机标头设置为您要连接的主机。
Tim was very close with his answer but he missed setting the host header properly.蒂姆非常接近他的答案,但他错过了正确设置主机标题。

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

For the record his answer does work with http://nodejs.org/ but that's because their server doesn't care the host header is incorrect.作为记录,他的回答确实适用于http://nodejs.org/,但那是因为他们的服务器不在乎主机标头是否不正确。

You can use request , I just found it's unbelievably easy to use proxy on node.js, just with one external "proxy" parameter, even more it supports HTTPS through a http proxy.您可以使用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);
  }
})

One thing that took me a while to figure out, use 'http' to access the proxy, even if you're trying to proxy through to a https server.我花了一段时间才弄清楚的一件事是,使用“http”访问代理,即使您尝试代理到 https 服务器。 This works for me using Charles (osx protocol analyser):这对我使用 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);
});

As @Renat here already mentioned, proxied HTTP traffic comes in pretty normal HTTP requests.正如这里的@Renat 已经提到的,代理 HTTP 流量来自非常正常的 HTTP 请求。 Make the request against the proxy, passing the full URL of the destination as the path.针对代理发出请求,将目标的完整 URL作为路径传递。

var http = require ('http');

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

I bought private proxy server, after purchase I got:我购买了私人代理服务器,购买后我得到:

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

And I wanted to use it.我想使用它。 First answer and second answer worked only for http(proxy) -> http(destination), however I wanted http(proxy) -> https(destination).第一个答案第二个答案仅适用于 http(proxy) -> http(destination),但是我想要 http(proxy) -> https(destination)。

And for https destination it would be better to use HTTP tunnel directly.对于 https 目的地,最好直接使用HTTP 隧道 I found solution here .我在这里找到了解决方案。

Node v8:节点 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()

Node v14:节点 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();

Thought I would add this module I found: https://www.npmjs.org/package/global-tunnel , which worked great for me (Worked immediately with all my code and third party modules with only the code below).以为我会添加我发现的这个模块: https://www.npmjs.org/package/global-tunnel ,它对我很有用(立即使用我的所有代码和第三方模块,只有下面的代码)。

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

Do this once, and all http (and https) in your application goes through the proxy.执行一次,应用程序中的所有 http(和 https)都会通过代理。

Alternately, calling或者,调用

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

Will use the http_proxy environment variable将使用http_proxy环境变量

The 'request' http package seems to have this feature: “请求”http 包似乎具有此功能:

https://github.com/mikeal/request https://github.com/mikeal/request

For example, the 'r' request object below uses localproxy to access its requests:例如,下面的“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)
  }
})

Unfortunately there are no "global" defaults so that users of libs that use this cannot amend the proxy unless the lib pass through http options...不幸的是,没有“全局”默认值,因此使用它的库的用户无法修改代理,除非库通过 http 选项...

HTH, Chris HTH,克里斯

In case you need to the use basic authorisation for your proxy provider, just use the following:如果您需要为您的代理提供商使用基本授权,只需使用以下内容:

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

Basically you don't need an explicit proxy support.基本上你不需要明确的代理支持。 Proxy protocol is pretty simple and based on the normal HTTP protocol.代理协议非常简单,基于普通的 HTTP 协议。 You just need to use your proxy host and port when connecting with HTTPClient.您只需要在与 HTTPClient 连接时使用您的代理主机和端口。 Example (from node.js docs):示例(来自 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();
...

So basically you connect to your proxy but do a request to "http://www.google.com".所以基本上你连接到你的代理,但请求“http://www.google.com”。

Node should support using the http_proxy environmental variable - so it is cross platform and works on system settings rather than requiring a per-application configuration. Node 应该支持使用 http_proxy 环境变量 - 所以它是跨平台的并且适用于系统设置,而不需要每个应用程序的配置。

Using the provided solutions, I would recommend the following:使用提供的解决方案,我会推荐以下内容:

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

Usage To use the method, effectively just replace http.get, for instance the following writes the index page of google to a file called test.htm:用法要使用该方法,只需替换 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"

I think there a better alternative to the answers as of 2019. We can use the global-tunnel-ng package to initialize proxy and not pollute the http or https based code everywhere.我认为截至 2019 年的答案有更好的替代方案。我们可以使用global-tunnel-ng包来初始化代理,而不是到处污染基于httphttps的代码。 So first install global-tunnel-ng package:所以首先安装global-tunnel-ng包:

npm install global-tunnel-ng

Then change your implementations to initialize proxy if needed as:然后根据需要更改您的实现以初始化代理:

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

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

Imskull's answer almost worked for me, but I had to make some changes. Imskull 的回答几乎对我有用,但我不得不做出一些改变。 The only real change is adding username, password, and setting rejectUnauthorized to false.唯一真正的变化是添加用户名、密码,并将rejectUnauthorized 设置为false。 I couldn't comment so I put this in an answer.我无法发表评论,所以我把它放在了一个答案中。

If you run the code it'll get you the titles of the current stories on Hacker News, per this tutorial: http://smalljs.org/package-managers/npm/如果您运行代码,它会根据本教程为您提供 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.');
    }
});

可能不是您希望的确切单行程序,但您可以查看http://github.com/nodejitsu/node-http-proxy,因为这可能会阐明如何将您的应用程序与 http 一起使用。客户端。

For using a proxy with https I tried the advice on this website (using dependency https-proxy-agent ) and it worked for me:为了使用带有 https 的代理,我尝试了本网站上的建议(使用依赖项https-proxy-agent ),它对我有用:

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

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

Based on the answers from this thread it would seem like you could use proxychains to run node.js through the proxy server:根据该线程的答案,您似乎可以使用代理通过代理服务器运行 node.js:
$ proxychains /path/to/node application.js

Personally I wasnt able to install any of the proxychains versions on Cygwin/Windows environment so couldn't test it.我个人无法在Cygwin/Windows环境中安装任何代理链版本,因此无法对其进行测试。

Furthermore, they also talked about using connect-proxy but I could not find any documentation on how to do this.此外,他们还谈到了使用连接代理,但我找不到任何有关如何执行此操作的文档。

In short, I'm still stuck, but maybe someone can use this info to find a suitable work-around.简而言之,我仍然被困住了,但也许有人可以使用此信息来找到合适的解决方法。

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

If you have the Basic http authentication scheme you have to make a base64 string of myuser:mypassword , and then add "Basic" in the beginning.如果您有Basic http 身份验证方案,则必须创建一个 base64 字符串myuser:mypassword ,然后在开头添加“Basic”。 That's the value of Proxy-Authorization header, here an example:这是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();

In nodejs you could use Buffer to encode在 nodejs 中,您可以使用Buffer进行编码

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

console.log(encodedData);

Just as example, in browsers you could encode in base64 using btoa() , useful in ajax requests in a browser without proxy settings performing a request using proxy.举个例子,在浏览器中,你可以使用btoa()在 base64 中编码,这在浏览器中的 ajax 请求中很有用,没有代理设置使用代理执行请求。

 var encodedData = btoa('myuser:mypassword') console.log(encodedData);

How to find wich scheme accepts the proxy server?如何找到哪个方案接受代理服务器?

If we don't have a custom DNS configured (that would throw something like ERR_NAME_NOT_RESOLVED), when we perform a request, the response (code 407) should inform in the response headers which http authentication scheme the proxy is using.如果我们没有配置自定义 DNS(这会抛出类似 ERR_NAME_NOT_RESOLVED 之类的东西),当我们执行请求时,响应(代码 407)应该在响应头中通知代理正在使用哪个 http 身份验证方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM