Come posso usare un proxy http con node.js http.Client?


137

Voglio effettuare una chiamata HTTP in uscita da node.js, usando lo standard http.Client. Ma non riesco a raggiungere il server remoto direttamente dalla mia rete e devo passare attraverso un proxy.

Come posso dire a node.js di usare il proxy?


1
Sto avendo lo stesso problema. Node.js è protetto da un firewall e non riesco a creare un client HTTP su un sito Web esterno.
ddallala,

Risposte:


153

La risposta di Tim Macfarlane era vicina per quanto riguarda l'uso di un proxy HTTP.

L'uso di un proxy HTTP (per richieste non sicure) è molto semplice. Ti connetti al proxy ed esegui normalmente la richiesta, tranne per il fatto che la parte del percorso include l'URL completo e l'intestazione dell'host è impostata sull'host a cui desideri connetterti.
Tim è stato molto vicino con la sua risposta ma ha perso l'impostazione corretta dell'intestazione 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);
});

Per la cronaca, la sua risposta funziona con http://nodejs.org/, ma è perché il loro server non si preoccupa che l'intestazione dell'host sia errata.


1
C'è un modo per utilizzare la porta https di proxy proxy http? sembra non abbia un metodo semplice
Gohan,

@Gohan Vedi la risposta di Chris di seguito per un esempio su come connettersi a un server HTTPS tramite proxy HTTP.
HairOfTheDog,

se ricevi una cattiva richiesta, inserisci il percorso: '/'
Laurent Debricon

9
Come posso integrare utente proxy e password proxy nel blocco opzioni?
Twistleton,

È cambiato? Anche con la destinazione finale come un altro server locale, ottengo un 404e il server di destinazione non riceve mai la richiesta.
OJFord

53

Puoi usare la richiesta , ho appena scoperto che è incredibilmente facile usare il proxy su node.js, solo con un parametro "proxy" esterno, ancora di più supporta HTTPS attraverso 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);
  }
})

1
Ha funzionato per entrambi httpe httpsnel mio caso, grazie mille
Samuel Bushi,

qualche idea sul perché questo non funzionerà per le pagine corp interne?
keinabel,

1
Sono sorpreso che le pagine corp interne siano dietro un proxy. Sei sicuro che il proxy non venga ignorato per le pagine interne? È su un altro vlan?
Chanoch,

Devi specificare l'autenticazione in qualche modo (lo pubblicherò qui se lo capissi)
Igor L.

Ho ricevuto questo errore utilizzando la richiesta con proxy: Errore: impossibile stabilire il tunneling socket, causa = connessione ECONNREFUSED 127.0.0.1:80
Federico Caccia

35

Una cosa che mi ci è voluto un po 'di tempo per capire, usa' http 'per accedere al proxy, anche se stai provando a fare il proxy su un server HTTPS. Questo funziona per me usando Charles (analizzatore di protocollo 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);
});

1
Il codice sopra non funziona per me, ed è relativo al problema github.com/joyent/node/issues/2474 controlla la risposta di koichik dobbiamo usare "method": "connect" e su "connect" event, abbiamo inviato informazioni sul percorso .
Palani,

16

Come già accennato da @Renat, il traffico HTTP con proxy arriva in richieste HTTP piuttosto normali. Invia la richiesta al proxy, passando l' URL completo della destinazione come percorso.

var http = require ('http');

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

2
Questo sembra funzionare anche se Fiddler lo chiama una violazione del protocollo che suggerisce che non è una richiesta HTTP corretta tramite proxy ...
Marc

11

Ho pensato di aggiungere questo modulo che ho trovato: https://www.npmjs.org/package/global-tunnel , che ha funzionato benissimo per me (ha funzionato immediatamente con tutto il mio codice e moduli di terze parti con solo il codice seguente).

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

Fallo una volta, e tutti gli http (e https) nella tua applicazione passano attraverso il proxy.

In alternativa, chiamando

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

Userà la http_proxyvariabile d'ambiente


2
Questo ha funzionato per me! In realtà in questo modo si disaccoppia il proxy dal codice e si utilizza la configurazione esistente per npm! questa è la strada da percorrere direi
cesaregb

@NeelBasu Sì, lo fa
maggiore-mann

10

Ho acquistato un server proxy privato, dopo l'acquisto ho ottenuto:

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

E volevo usarlo. La prima e la seconda risposta hanno funzionato solo per http (proxy) -> http (destinazione), tuttavia volevo http (proxy) -> https (destinazione).

E per la destinazione https sarebbe meglio usare il tunnel HTTP direttamente. Ho trovato una soluzione qui . Codice finale:

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

7

Il pacchetto http 'request' sembra avere questa funzione:

https://github.com/mikeal/request

Ad esempio, l'oggetto richiesta 'r' di seguito utilizza localproxy per accedere alle sue richieste:

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

Sfortunatamente non ci sono impostazioni predefinite "globali" in modo che gli utenti di librerie che lo utilizzano non possano modificare il proxy a meno che la libreria non passi attraverso le opzioni http ...

HTH, Chris


il pacchetto http di richiesta rende più facile consentire al codice di alternare tra uso proxy e non proxy (che è abbastanza utile sul mio laptop).
Jon Madison,

5

Fondamentalmente non è necessario un supporto proxy esplicito. Il protocollo proxy è piuttosto semplice e basato sul normale protocollo HTTP. Devi solo usare il tuo host proxy e la tua porta quando ti connetti a HTTPClient. Esempio (dai documenti 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();
...

Quindi sostanzialmente ti connetti al tuo proxy ma fai una richiesta a "http://www.google.com".


3
http.createClient è deprecato, Tim Macfarlane utilizza il più recente http.get di seguito
sami

1
Apparentemente non funzionerà più con node.js dalla v5.6 poiché hanno rimosso createClient .
Marc,

5

Nel caso in cui sia necessario utilizzare l'autorizzazione di base per il proprio provider proxy, utilizzare semplicemente quanto segue:

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

1
dove posso trovare "FarmerAdapter"?
Alex,

3

Il nodo dovrebbe supportare l'utilizzo della variabile ambientale http_proxy, quindi è multipiattaforma e funziona sulle impostazioni di sistema piuttosto che richiedere una configurazione per applicazione.

Utilizzando le soluzioni fornite, consiglierei quanto segue:

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

Utilizzo Per utilizzare il metodo, sostituire semplicemente http.get, ad esempio quanto segue scrive la pagina dell'indice di google in un file chiamato 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"

L'impostazione di http_proxy non sembra avere alcun effetto durante l'esecuzione di Node su Windows.
EricLaw,

Dovrebbe funzionare su Windows (questo è il sistema principale che sto usando). Accertarsi di aver reimpostato l'impostazione della reimpostazione della sessione del terminale (se impostata tramite il pannello di controllo e non impostata). Dovresti essere in grado di verificare che sia impostato correttamente usando echo% HTTP_PROXY% O ancora meglio dovresti usare il nodo stesso nodo -e "console.log (process.env.http_proxy);" Questo ha funzionato per me su Windows, quindi buona fortuna.
Luca

1

La risposta di Imskull ha quasi funzionato per me, ma ho dovuto apportare alcune modifiche. L'unica vera modifica è l'aggiunta di nome utente, password e impostazione rifiuta non autorizzata su falso. Non ho potuto commentare, quindi ho inserito una risposta.

Se esegui il codice otterrai i titoli delle storie attuali su Hacker News, per questo tutorial: 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

Penso che ci sia un'alternativa migliore alle risposte a partire dal 2019. Possiamo usare il global-tunnel-ngpacchetto per inizializzare il proxy e non inquinare il codice httpo httpsbasato ovunque. Quindi primo global-tunnel-ngpacchetto di installazione :

npm install global-tunnel-ng

Quindi modificare le implementazioni per inizializzare il proxy se necessario come:

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

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


0

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

Sulla base delle risposte di questo thread sembrerebbe che potresti usare proxychains per eseguire node.js attraverso il server proxy:
$ proxychains /path/to/node application.js

Personalmente non sono stato in grado di installare nessuna delle versioni di proxychains su Cygwin / Windows ambiente , quindi non ho potuto testarlo.

Inoltre, hanno anche parlato dell'utilizzo di connect-proxy ma non sono riuscito a trovare alcuna documentazione su come eseguire questa operazione.

In breve, sono ancora bloccato, ma forse qualcuno può usare queste informazioni per trovare una soluzione adeguata.


aggiornamento: dopo alcune indagini ho scoperto che non potevo costruire proxychain su CygWin perché RTLD_NEXT non è supportato.
ddallala,


0

usa 'https-proxy-agent' in questo modo

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

Se si dispone dello schema di autenticazione http di base , è necessario creare una stringa base64 myuser:mypassword, quindi aggiungere "Base" all'inizio. Questo è il valore dell'intestazione Proxy-Authorization , qui un esempio:

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 è possibile utilizzare Buffer per codificare

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

console.log(encodedData);

Proprio come ad esempio, nei browser è possibile codificare in base64 usando btoa () , utile nelle richieste ajax in un browser senza impostazioni proxy che eseguono una richiesta tramite proxy.

var encodedData = btoa('myuser:mypassword')

console.log(encodedData);

Come trovare quale schema accetta il server proxy?

Se non abbiamo configurato un DNS personalizzato (che genererebbe qualcosa come ERR_NAME_NOT_RESOLVED), quando eseguiamo una richiesta, la risposta (codice 407) dovrebbe indicare nelle intestazioni di risposta quale schema di autenticazione http sta utilizzando il proxy.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.