Wie kann ich einen http-Proxy mit node.js http.Client verwenden?

137

Ich möchte einen ausgehenden HTTP-Aufruf von node.js unter Verwendung des Standards tätigen http.Client. Ich kann den Remote-Server jedoch nicht direkt von meinem Netzwerk aus erreichen und muss einen Proxy verwenden.

Wie kann ich node.js anweisen, den Proxy zu verwenden?

Christian Berg
quelle
1
Ich habe das gleiche Problem. Node.js befindet sich hinter einer Firewall und ich kann keinen HTTPClient für eine externe Website erstellen.
Ddallala

Antworten:

152

Die Antwort von Tim Macfarlane war in Bezug auf die Verwendung eines HTTP-Proxys nah.

Die Verwendung eines HTTP-Proxys (für nicht sichere Anforderungen) ist sehr einfach. Sie stellen eine Verbindung zum Proxy her und stellen die Anforderung normal, mit der Ausnahme, dass der Pfadteil die vollständige URL enthält und der Host-Header auf den Host festgelegt ist, zu dem Sie eine Verbindung herstellen möchten.
Tim war sehr nah an seiner Antwort, aber er vermisste es, den Host-Header richtig einzustellen.

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

Für die Aufzeichnung funktioniert seine Antwort mit http://nodejs.org/, aber das liegt daran, dass es ihrem Server egal ist, dass der Host-Header falsch ist.

Samuel
quelle
1
Gibt es eine Möglichkeit, den https-Port für die http-Proxy-Verbindung zu verwenden? scheint hat keine einfache Methode
Gohan
@Gohan In der folgenden Antwort von Chris finden Sie ein Beispiel für die Verbindung zu einem https-Server über einen http-Proxy.
HairOfTheDog
Wenn Sie eine schlechte Anfrage erhalten, geben Sie den Pfad ein: '/'
Laurent Debricon
9
Wie kann ich Proxy-Benutzer und Proxy-Passwort in den Optionsblock integrieren?
Twistleton
Hat sich das geändert? Selbst mit dem endgültigen Ziel als einem anderen lokalen Server erhalte ich eine 404, und der Zielserver erhält die Anfrage nie.
OJFord
53

Sie können request verwenden . Ich habe gerade festgestellt, dass es unglaublich einfach ist, Proxy auf node.js zu verwenden, nur mit einem externen "Proxy" -Parameter. Außerdem unterstützt es HTTPS über einen http-Proxy.

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);
  }
})
Imskull
quelle
1
Arbeitete für beide httpund httpsin meinem Fall, vielen Dank
Samuel Bushi
Irgendwelche Ideen, warum dies für interne Unternehmensseiten nicht funktioniert?
keinabel
1
Ich bin überrascht, dass sich interne Unternehmensseiten hinter einem Proxy befinden. Sind Sie sicher, dass der Proxy für interne Seiten nicht umgangen wird? Ist es auf einem anderen VLAN?
Chanoch
Sie müssen die Authentifizierung irgendwie angeben (werde sie hier veröffentlichen, wenn ich es herausfinde)
Igor L.
Ich habe diesen Fehler bei der Anforderung mit Proxy erhalten: Fehler: Tunneling-Socket konnte nicht hergestellt werden, Ursache = Verbindung ECONNREFUSED 127.0.0.1:80
Federico Caccia
35

Eine Sache, die ich eine Weile gebraucht habe, um herauszufinden, verwenden Sie 'http', um auf den Proxy zuzugreifen, selbst wenn Sie versuchen, einen Proxy zu einem https-Server durchzuführen. Dies funktioniert bei mir mit Charles (osx protocol analyzer):

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);
});
Chris
quelle
1
Der obige Code funktioniert bei mir nicht und bezieht sich auf das Problem github.com/joyent/node/issues/2474. Überprüfen Sie die Antwort von koichik. Wir müssen "method" verwenden: "connect" und beim Ereignis "connect" haben wir Pfadinformationen gesendet .
Palani
16

Wie hier bereits erwähnt, kommt der Proxy-HTTP-Verkehr in ganz normalen HTTP-Anforderungen. Stellen Sie die Anforderung an den Proxy und übergeben Sie die vollständige URL des Ziels als Pfad.

var http = require ('http');

http.get ({
    host: 'my.proxy.com',
    port: 8080,
    path: 'http://nodejs.org/'
}, function (response) {
    console.log (response);
});
Tim Macfarlane
quelle
2
Dies scheint zu funktionieren, obwohl Fiddler es als Protokollverletzung bezeichnet, was darauf hindeutet, dass es sich nicht um eine ordnungsgemäße HTTP-Anfrage über Proxy handelt ...
Marc
11

Ich dachte, ich würde dieses Modul hinzufügen, das ich gefunden habe: https://www.npmjs.org/package/global-tunnel , was für mich großartig funktioniert hat (funktionierte sofort mit allen meinen Code- und Drittanbieter-Modulen mit nur dem folgenden Code).

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

Wenn Sie dies einmal tun, durchlaufen alle http (und https) in Ihrer Anwendung den Proxy.

Alternativ anrufen

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

Verwendet die http_proxyUmgebungsvariable

Major-Mann
quelle
2
Das hat bei mir funktioniert! Auf diese Weise entkoppeln Sie den Proxy vom Code und verwenden die vorhandene Konfiguration für npm! Das ist der
richtige
@ NeelBasu Ja, das tut es
Major-Mann
9

Ich habe einen privaten Proxyserver gekauft und nach dem Kauf Folgendes erhalten:

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

Und ich wollte es benutzen. Die erste und die zweite Antwort funktionierten nur für http (Proxy) -> http (Ziel), ich wollte jedoch http (Proxy) -> https (Ziel).

Und für das https-Ziel ist es besser, den HTTP-Tunnel direkt zu verwenden. Ich habe hier eine Lösung gefunden . Endgültiger Code:

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()
Alexey Volodko
quelle
7

Das http-Paket 'request' scheint folgende Funktion zu haben:

https://github.com/mikeal/request

Das folgende Anforderungsobjekt 'r' verwendet beispielsweise localproxy, um auf seine Anforderungen zuzugreifen:

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

Leider gibt es keine "globalen" Standardeinstellungen, sodass Benutzer von Bibliotheken, die diese verwenden, den Proxy nur ändern können, wenn die Bibliothek die http-Optionen durchläuft ...

HTH, Chris

Chris Kimpton
quelle
Das http-Paket für Anfragen erleichtert das Umschalten zwischen Proxy- und Nicht-Proxy-Nutzung (was auf meinem Laptop sehr nützlich ist).
Jon Madison
5

Grundsätzlich benötigen Sie keine explizite Proxy-Unterstützung. Das Proxy-Protokoll ist ziemlich einfach und basiert auf dem normalen HTTP-Protokoll. Sie müssen nur Ihren Proxy-Host und -Port verwenden, wenn Sie eine Verbindung mit HTTPClient herstellen. Beispiel (aus den Dokumenten von 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();
...

Sie stellen also im Grunde eine Verbindung zu Ihrem Proxy her, stellen jedoch eine Anfrage an "http://www.google.com".

Renat
quelle
3
http.createClient ist veraltet, Tim Macfarlane verwendet das neuere http.get unten
sami
1
Dies funktioniert anscheinend nicht mehr mit node.js ab Version 5.6, da createClient entfernt wurde .
Marc
5

Wenn Sie die Basisberechtigung für Ihren Proxy-Anbieter verwenden müssen, verwenden Sie einfach Folgendes:

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();
Vyacheslav Voronchuk
quelle
1
Wo finde ich "FarmerAdapter"?
Alex
3

Der Knoten sollte die Verwendung der Umgebungsvariablen http_proxy unterstützen. Sie ist also plattformübergreifend und funktioniert mit Systemeinstellungen, anstatt eine Konfiguration pro Anwendung zu erfordern.

Unter Verwendung der bereitgestellten Lösungen würde ich Folgendes empfehlen:

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

Verwendung Um die Methode zu verwenden, ersetzen Sie einfach http.get. Beispiel: Im Folgenden wird die Indexseite von Google in eine Datei namens test.htm geschrieben:

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"
Luke
quelle
Das Festlegen von http_proxy scheint keine Auswirkungen zu haben, wenn Node unter Windows ausgeführt wird.
EricLaw
Es sollte unter Windows funktionieren (das ist das primäre System, das ich verwende). Stellen Sie nach dem Festlegen der Einstellung sicher, dass Sie Ihre Terminalsitzung zurückgesetzt haben (falls über das Bedienfeld festgelegt und nicht festgelegt). Sie sollten in der Lage sein, die korrekte Einstellung mit echo% HTTP_PROXY% zu überprüfen. Oder noch besser, Sie sollten den Knoten selbst verwenden. Knoten -e "console.log (process.env.http_proxy);" Das hat bei mir unter Windows funktioniert, also viel Glück.
Luke
1

Imskulls Antwort hat fast für mich funktioniert, aber ich musste einige Änderungen vornehmen. Die einzige wirkliche Änderung besteht darin, Benutzername, Passwort und die Einstellung "RejectUnauthorized" auf "false" zu setzen. Ich konnte keinen Kommentar abgeben, also habe ich dies in eine Antwort eingefügt.

Wenn Sie den Code ausführen, erhalten Sie die Titel der aktuellen Geschichten in Hacker News gemäß diesem 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.');
    }
});
Wassili Kuschakow
quelle
1

Ich denke, es gibt eine bessere Alternative zu den Antworten ab 2019. Wir können das global-tunnel-ngPaket verwenden, um den Proxy zu initialisieren und den httpoder httpsbasierten Code nicht überall zu verschmutzen . Installieren Sie also zuerst das global-tunnel-ngPaket:

npm install global-tunnel-ng

Ändern Sie dann Ihre Implementierungen, um den Proxy bei Bedarf wie folgt zu initialisieren:

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

globalTunnel.initialize({
  host: 'proxy.host.name.or.ip',
  port: 8080
});
Ringträger
quelle
0

Möglicherweise ist dies nicht der genaue Einzeiler, auf den Sie gehofft haben, aber Sie können einen Blick auf http://github.com/nodejitsu/node-http-proxy werfen, da dies möglicherweise Aufschluss darüber gibt, wie Sie Ihre App mit http verwenden können. Klient.

Fullstacklife
quelle
1
Wie ist das hilfreich?
Jerinaw
0

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

Basierend auf den Antworten aus diesem Thread scheint es, als könnten Sie Proxy- Ketten verwenden , um node.js über den Proxyserver auszuführen:
$ proxychains /path/to/node application.js

Persönlich konnte ich keine der Proxy-Chains- Versionen in einer Cygwin / Windows- Umgebung installieren und konnte sie daher nicht testen.

Außerdem wurde über die Verwendung von Connect-Proxy gesprochen, aber ich konnte keine Dokumentation dazu finden.

Kurz gesagt, ich stecke immer noch fest, aber vielleicht kann jemand diese Informationen verwenden, um eine geeignete Lösung zu finden.

ddallala
quelle
Update: Nach einigen Nachforschungen wurde festgestellt, dass ich keine Proxy-Ketten auf CygWin erstellen konnte, da RTLD_NEXT nicht unterstützt wird.
Ddallala
0

Verwenden Sie 'https-proxy-agent' wie folgt

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)=>{...});
Schlechtes Grün
quelle
0

Wenn Sie über das Basic http-Authentifizierungsschema verfügen, müssen Sie eine base64-Zeichenfolge erstellen myuser:mypasswordund dann am Anfang "Basic" hinzufügen. Das ist der Wert des Proxy-Authorization- Headers, hier ein Beispiel:

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 können Sie Buffer zum Codieren verwenden

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

console.log(encodedData);

In Browsern können Sie beispielsweise in base64 mit btoa () codieren. Dies ist nützlich bei Ajax-Anforderungen in einem Browser, ohne dass Proxy-Einstellungen eine Anforderung mit Proxy ausführen.

var encodedData = btoa('myuser:mypassword')

console.log(encodedData);

Wie finde ich heraus, welches Schema den Proxyserver akzeptiert?

Wenn wir kein benutzerdefiniertes DNS konfiguriert haben (das so etwas wie ERR_NAME_NOT_RESOLVED auslösen würde), sollte die Antwort (Code 407) bei der Ausführung einer Anforderung in den Antwortheadern angeben, welches http-Authentifizierungsschema der Proxy verwendet.

Emeeus
quelle