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?
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.
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);
}
})
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);
});
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);
});
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
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
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".
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();
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"
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.');
}
});
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.
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
});
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.
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/
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)=>{...});
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.