web-dev-qa-db-fra.com

Comment utiliser un proxy http avec node.js http.Client?

Je souhaite effectuer un appel HTTP sortant à partir de node.js, à l'aide du http.Client standard. Mais je ne peux pas atteindre le serveur distant directement à partir de mon réseau et je dois passer par un proxy. 

Comment puis-je dire à node.js d'utiliser le proxy?

118
Christian Berg

Tim Macfarlane 's answer était proche de l'utilisation d'un proxy HTTP.

Utiliser un proxy HTTP (pour les requêtes non sécurisées) est très simple. Vous vous connectez au proxy et faites la demande normalement, sauf que la partie chemin contient l'URL complète et que l'en-tête de l'hôte est défini sur l'hôte auquel vous souhaitez vous connecter.
Tim était très proche de sa réponse mais il manqua de définir correctement l'en-tête Host.

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

Pour mémoire, sa réponse fonctionne avec http://nodejs.org/ mais c'est parce que leur serveur ne se soucie pas de l'en-tête Host est incorrect.

132
Samuel

Vous pouvez utiliser request , Je viens de découvrir que c’est incroyablement facile d’utiliser un proxy sur node.js, avec juste un paramètre "proxy" externe, et de plus il prend en charge HTTPS via un proxy http.

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

Une chose qui m'a pris un certain temps à comprendre, utilisez «http» pour accéder au proxy, même si vous essayez de proxy sur un serveur https. Cela fonctionne pour moi avec Charles (analyseur de protocole 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);
});
31
Chris

Comme @Renat ici déjà mentionné, le trafic HTTP traité par proxy se présente sous forme de requêtes HTTP normales. Faites la demande contre le proxy, en passant le URL complet de la destination comme chemin.

var http = require ('http');

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

J'ai pensé ajouter ce module: https://www.npmjs.org/package/global-tunnel , ce qui a très bien fonctionné pour moi (fonctionne immédiatement avec tout mon code et les modules tiers avec uniquement le code ci-dessous ).

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

Faites cela une fois, et tous les http (et https) de votre application passent par le proxy.

Alternativement, appelant

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

Utilisera la variable d'environnement http_proxy

9
major-mann

Le paquet http 'request' semble avoir cette fonctionnalité: 

https://github.com/mikeal/request

Par exemple, l'objet de requête 'r' ci-dessous utilise localproxy pour accéder à ses requêtes:

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

Malheureusement, il n'y a pas de valeur par défaut "globale", de sorte que les utilisateurs de bibliothèques utilisant cette fonction ne peuvent pas modifier le proxy, sauf si la bibliothèque passe par les options http ...

HTH, Chris

7
Chris Kimpton

En gros, vous n'avez pas besoin d'un support de proxy explicite. Le protocole proxy est assez simple et basé sur le protocole HTTP normal. Vous devez simplement utiliser votre hôte proxy et votre port lors de la connexion à HTTPClient. Exemple (à partir de la documentation de 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();
...

Donc, en gros, vous vous connectez à votre proxy mais faites une demande à "http://www.google.com".

5
Renat

Si vous devez utiliser l'autorisation de base pour votre fournisseur de proxy, utilisez simplement les éléments suivants:

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

Le nœud doit prendre en charge l'utilisation de la variable d'environnement http_proxy. Il est donc multiplateforme et fonctionne avec les paramètres système plutôt que de nécessiter une configuration par application.

En utilisant les solutions fournies, je recommanderais ce qui suit:

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

Utilisation Pour utiliser cette méthode, remplacez simplement http.get, par exemple, écrit la page d'index de google dans un fichier appelé 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"
3
Luke

J'ai acheté un serveur proxy privé, après l'achat, j'ai obtenu:

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

Et je voulais l'utiliser. Première réponse et deuxième réponse fonctionnait uniquement pour http (proxy) -> http (destination), mais je voulais http (proxy) -> https (destination).

Et pour la destination https, il serait préférable d'utiliser tunnel HTTP directement .. J'ai trouvé la solution ici . Code final:

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

La réponse d'Imskull a presque fonctionné pour moi, mais j'ai dû faire quelques changements. La seule modification réelle est l’ajout du nom d’utilisateur, du mot de passe et de la définition de rejetUnauthorized à false. Je ne pouvais pas commenter alors j'ai mis cela dans une réponse. 

Si vous exécutez le code, vous obtiendrez les titres des articles actuels sur Hacker News, selon ce tutoriel: 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
Vasily Kushakov

Ce n'est peut-être pas le type de vol que vous espériez mais vous pouvez jeter un coup d'œil à http://github.com/nodejitsu/node-http-proxy car cela pourrait vous éclairer sur la manière dont vous pouvez utiliser votre application avec http.Client.

0
fullstacklife

Je pense qu'il existe une meilleure alternative aux réponses à partir de 2019. Nous pouvons utiliser le paquetage global-tunnel-ng pour initialiser le proxy et ne pas polluer le code basé sur http ou https partout. Donc, installez d'abord le paquet global-tunnel-ng:

npm install global-tunnel-ng

Puis changez vos implémentations pour initialiser le proxy si nécessaire en tant que:

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

globalTunnel.initialize({
  Host: 'proxy.Host.name.or.ip',
  port: 8080
});
0
ring bearer

Si vous avez le schéma d'authentification http Basic http , vous devez créer une chaîne base64 de myuser:mypassword, puis ajouter "Basic" au début. C'est la valeur de Proxy-Authorization header, voici un exemple:

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

Dans nodejs, vous pouvez utiliser Buffer pour encoder 

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

console.log(encodedData);

À titre d’exemple, dans les navigateurs, vous pouvez encoder en base64 avec btoa () , ce qui est utile dans les requêtes ajax dans un navigateur sans paramètres de proxy effectuant une requête à l’aide de proxy. 

var encodedData = btoa('myuser:mypassword')

console.log(encodedData);

Comment trouver quel schéma accepte le serveur proxy? 

Si nous n'avons pas de DNS personnalisé configuré (ce qui donnerait quelque chose comme ERR_NAME_NOT_RESOLVED), lorsque nous effectuons une demande, la réponse (code 407) doit indiquer dans les en-têtes de réponse quel schéma d'authentification http utilise le proxy.

0
Emeeus

Pour utiliser un proxy avec https, j'ai essayé les conseils de ce site Web (en utilisant dependency https-proxy-agent) et cela a fonctionné pour moi:

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

0
Jonathan Benn

utilisez 'https-proxy-agent' comme ceci

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
Bad Green

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

D'après les réponses à ce fil, il semblerait que vous pourriez utiliser proxychains Pour exécuter node.js via le serveur proxy:
$ proxychains /path/to/node application.js 

Personnellement, je n'ai pas pu installer aucune des versions de proxychains sur l'environnement Cygwin/Windows, je n'ai donc pas pu le tester.

En outre, ils ont également parlé de l'utilisation de connect-proxy, mais je n'ai trouvé aucune documentation sur la procédure à suivre.

En bref, je suis toujours bloqué, mais peut-être que quelqu'un pourra utiliser cette information pour trouver une solution de contournement appropriée.

0
ddallala