簡體   English   中英

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

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

我想使用標准的http.Client從 node.js 進行傳出 HTTP 調用。 但是我無法直接從我的網絡訪問遠程服務器,需要通過代理。

我如何告訴 node.js 使用代理?

關於使用 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/,但那是因為他們的服務器不在乎主機標頭是否不正確。

您可以使用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);
  }
})

我花了一段時間才弄清楚的一件事是,使用“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);
});

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

我購買了私人代理服務器,購買后我得到:

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(proxy) -> http(destination),但是我想要 http(proxy) -> https(destination)。

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

以為我會添加我發現的這個模塊: 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環境變量

“請求”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,克里斯

如果您需要為您的代理提供商使用基本授權,只需使用以下內容:

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

基本上你不需要明確的代理支持。 代理協議非常簡單,基於普通的 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”。

Node 應該支持使用 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

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"

我認為截至 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
});

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

只需使用代理包裝器運行 nodejs,例如tsocks tsocks node myscript.js

原解決方案: 在NodeJS中通過SOCKS5代理做http請求

更多信息: https : //www.binarytides.com/proxify-applications-with-tsocks-and-proxychains-on-ubuntu/

對於 Windows: https : //superuser.com/questions/319516/how-to-force-any-program-to-use-socks

可能不是您希望的確切單行程序,但您可以查看http://github.com/nodejitsu/node-http-proxy,因為這可能會闡明如何將您的應用程序與 http 一起使用。客戶端。

為了使用帶有 https 的代理,我嘗試了本網站上的建議(使用依賴項https-proxy-agent ),它對我有用:

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

根據該線程的答案,您似乎可以使用代理通過代理服務器運行 node.js:
$ proxychains /path/to/node application.js

我個人無法在Cygwin/Windows環境中安裝任何代理鏈版本,因此無法對其進行測試。

此外,他們還談到了使用連接代理,但我找不到任何有關如何執行此操作的文檔。

簡而言之,我仍然被困住了,但也許有人可以使用此信息來找到合適的解決方法。

像這樣使用“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)=>{...});

如果您有Basic 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 身份驗證方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM