Jak mogę używać proxy HTTP z http.Client node.js?


137

Chcę wykonać wychodzące połączenie HTTP z node.js, używając standardu http.Client. Ale nie mogę połączyć się ze zdalnym serwerem bezpośrednio z mojej sieci i muszę przejść przez serwer proxy.

Jak powiedzieć node.js, aby używał proxy?


1
Mam ten sam problem. Node.js jest za zaporą ogniową i nie mogę utworzyć klienta HTTP dla zewnętrznej witryny internetowej.
— ddallala

Odpowiedzi:


153

Tim Macfarlane „s odpowiedź była blisko w odniesieniu do korzystania z serwera proxy HTTP.

Korzystanie z serwera proxy HTTP (w przypadku niezabezpieczonych żądań) jest bardzo proste. Łączysz się z serwerem proxy i wysyłasz żądanie normalnie, z tym wyjątkiem, że część ścieżki zawiera pełny adres URL, a nagłówek hosta jest ustawiony na hosta, z którym chcesz się połączyć.
Tim był bardzo blisko swojej odpowiedzi, ale przegapił prawidłowe ustawienie nagłówka hosta.

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

Dla przypomnienia, jego odpowiedź działa z http://nodejs.org/, ale to dlatego, że ich serwer nie dba o to, że nagłówek hosta jest nieprawidłowy.


1
Czy istnieje sposób korzystania z portu HTTPS połączenia proxy HTTP? wydaje się, że nie ma łatwej metody
— Gohan

@Gohan Zobacz odpowiedź Chrisa poniżej, aby zobaczyć przykład połączenia z serwerem https za pośrednictwem serwera proxy http.
— HairOfTheDog,

jeśli otrzymasz złe żądanie, umieść ścieżkę: „/”
— Laurent Debricon

9
Jak mogę zintegrować użytkownika proxy i hasło proxy w bloku opcji?
— Twistleton

Czy to się zmieniło? Nawet jeśli ostateczne miejsce docelowe jest innym lokalnym serwerem, otrzymuję a 404, a serwer docelowy nigdy nie otrzymuje żądania.
— OJFord

53

Możesz użyć request , właśnie odkryłem, że jest niewiarygodnie łatwy w użyciu proxy na node.js, tylko z jednym zewnętrznym parametrem "proxy", a nawet bardziej obsługuje HTTPS przez 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
Pracował dla obu httpi httpsw moim przypadku, wielkie dzięki
— Samuel Bushi

jakieś pomysły, dlaczego to nie zadziała na wewnętrznych stronach firmowych?
— keinabel

1
Dziwię się, że wewnętrzne strony firmowe znajdują się za proxy. Czy jesteś pewien, że serwer proxy nie jest pomijany w przypadku stron wewnętrznych? Czy jest na innej sieci VLAN?
— Chanoch,

Musisz jakoś określić uwierzytelnianie (wyślę to tutaj, jeśli to rozgryzę)
— Igor L.

Otrzymałem ten błąd, używając żądania z proxy: Błąd: nie można ustanowić gniazda tunelowania, przyczyna = połączenie ECONNREFUSED 127.0.0.1:80
— Federico Caccia

35

Jedna rzecz, której zrozumienie zajęło mi trochę czasu, użyj „http”, aby uzyskać dostęp do serwera proxy, nawet jeśli próbujesz połączyć się z serwerem https. To działa dla mnie przy użyciu Charlesa (analizator protokołu 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
Powyższy kod u mnie nie działa, a jest to związane z problemem github.com/joyent/node/issues/2474 sprawdź odpowiedź koichika musimy użyć "metoda": "connect" i na zdarzeniu "connect" wysłaliśmy informację o ścieżce .
— Palani

16

Jak już wspomniał @Renat, przez proxy ruch HTTP przychodzi w całkiem normalnych żądaniach HTTP. Prześlij żądanie do serwera proxy, przekazując jako ścieżkę pełny adres URL miejsca docelowego.

var http = require ('http');

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

2
Wydaje się, że to działa, chociaż Fiddler nazywa to naruszeniem protokołu, co sugeruje, że nie jest to właściwe żądanie HTTP przez proxy ...
— Marc

11

Pomyślałem, że dodam ten moduł, który znalazłem: https://www.npmjs.org/package/global-tunnel , który działał świetnie dla mnie (działał natychmiast z całym moim kodem i modułami stron trzecich tylko z kodem poniżej).

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

Zrób to raz, a wszystkie adresy http (i https) w Twojej aplikacji będą przechodzić przez serwer proxy.

Alternatywnie dzwonię

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

Użyje http_proxy zmiennej środowiskowej


2
To zadziałało dla mnie! Właściwie w ten sposób odłączasz proxy od kodu i używasz istniejącej konfiguracji npm! to jest droga, powiedziałbym
— cesaregb

@NeelBasu Tak, tak
— major-mann

9

Kupiłem prywatny serwer proxy, po zakupie otrzymałem:

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

I chciałem to wykorzystać. Pierwsza odpowiedź i druga odpowiedź działały tylko dla http (proxy) -> http (miejsce docelowe), jednak chciałem http (proxy) -> https (miejsce docelowe).

A w przypadku miejsca docelowego https lepiej byłoby bezpośrednio użyć tunelu HTTP . Tutaj znalazłem rozwiązanie . Kod końcowy:

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

Wydaje się, że pakiet HTTP „request” ma tę funkcję:

https://github.com/mikeal/request

Na przykład poniższy obiekt żądania `` r '' używa lokalnego serwera proxy, aby uzyskać dostęp do swoich żądań:

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

Niestety nie ma "globalnych" wartości domyślnych, więc użytkownicy bibliotek korzystających z tego nie mogą zmieniać proxy, chyba że biblioteka przejdzie przez opcje http ...

HTH, Chris


pakiet request http ułatwia zezwalanie kodowi na przełączanie się między używaniem proxy i nie proxy (co jest całkiem przydatne na moim laptopie).
— Jon Madison

5

Zasadniczo nie potrzebujesz jawnej obsługi proxy. Protokół proxy jest dość prosty i oparty na normalnym protokole HTTP. Wystarczy użyć hosta proxy i portu podczas łączenia się z HTTPClient. Przykład (z dokumentacji 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();
...

Zasadniczo łączysz się z serwerem proxy, ale wysyłasz żądanie do „http://www.google.com”.


3
http.createClient jest przestarzały, Tim Macfarlane używa nowszego http.get poniżej
— sami

1
Najwyraźniej nie będzie to już działać z node.js od wersji 5.6, ponieważ usunęli createClient .
— Marc

5

W przypadku, gdy potrzebujesz podstawowej autoryzacji dla swojego dostawcy proxy, użyj następujących:

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
gdzie mogę znaleźć „FarmerAdapter”?
— Alex

3

Węzeł powinien obsługiwać zmienną środowiskową http_proxy - jest więc wieloplatformowy i działa na ustawieniach systemu, a nie wymaga konfiguracji na aplikację.

Korzystając z dostarczonych rozwiązań, polecam:

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

Użycie Aby skorzystać z tej metody, efektywnie wystarczy zamienić http.get, na przykład poniższy zapis zapisuje stronę indeksową google do pliku o nazwie 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"

Wydaje się, że ustawienie http_proxy nie ma żadnego wpływu podczas uruchamiania Node w systemie Windows.
— EricLaw,

Powinien działać pod Windows (to jest podstawowy system, którego używam). Upewnij się, że po ustawieniu ustawienia zresetowałeś sesję terminala (jeśli została ustawiona za pośrednictwem panelu sterowania i nie została ustawiona). Powinieneś być w stanie sprawdzić, czy jest poprawnie ustawiony za pomocą echo% HTTP_PROXY% Lub jeszcze lepiej powinieneś użyć samego węzła node -e "console.log (process.env.http_proxy);" To działało dla mnie pod Windows, więc powodzenia.
— Łukasz

1

Odpowiedź Imskulla prawie mi pomogła, ale musiałem wprowadzić pewne zmiany. Jedyną prawdziwą zmianą jest dodanie nazwy użytkownika, hasła i ustawienia odrzucenia na fałsz. Nie mogłem komentować, więc umieściłem to w odpowiedzi.

Jeśli uruchomisz kod, otrzymasz tytuły aktualnych artykułów w Hacker News, zgodnie z tym samouczkiem: 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

Myślę, że istnieje lepsza alternatywa dla odpowiedzi z 2019 roku. Możemy użyć global-tunnel-ngpakietu do zainicjowania proxy i nie zanieczyszczać kodu httplub httpsopartego na nim wszędzie. Więc najpierw zainstaluj global-tunnel-ngpakiet:

npm install global-tunnel-ng

Następnie zmień swoje implementacje, aby w razie potrzeby zainicjować serwer proxy, tak jak:

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

Na podstawie odpowiedzi z tego wątku wydaje się, że możesz użyć proxychains do uruchomienia node.js przez serwer proxy:
$ proxychains /path/to/node application.js

Osobiście nie byłem w stanie zainstalować żadnej wersji proxychains w środowisku Cygwin / Windows, więc nie mogłem tego przetestować.

Co więcej, rozmawiali również o używaniu connect-proxy, ale nie mogłem znaleźć żadnej dokumentacji, jak to zrobić.

Krótko mówiąc, nadal utknąłem, ale może ktoś może wykorzystać te informacje, aby znaleźć odpowiednie obejście.


aktualizacja: po pewnym dochodzeniu okazało się, że nie mogę zbudować łańcuchów proxy na CygWin, ponieważ RTLD_NEXT nie jest obsługiwany.
— ddallala


0

użyj „https-proxy-agent” w ten sposób

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

Jeśli masz podstawowy schemat uwierzytelniania HTTP, musisz utworzyć ciąg base64 myuser:mypassword, a następnie dodać na początku „Basic”. To wartość nagłówka Proxy-Authorization , tutaj przykład:

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

W nodejs możesz użyć bufora do kodowania

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

console.log(encodedData);

Na przykład w przeglądarkach można kodować w base64 za pomocą btoa () , przydatne w żądaniach ajax w przeglądarce bez ustawień proxy, wykonując żądanie za pomocą proxy.

var encodedData = btoa('myuser:mypassword')

console.log(encodedData);

Jak znaleźć schemat, który akceptuje serwer proxy?

Jeśli nie mamy skonfigurowanego niestandardowego DNS (który wyrzuciłby coś takiego jak ERR_NAME_NOT_RESOLVED), kiedy wykonujemy żądanie, odpowiedź (kod 407) powinna informować w nagłówkach odpowiedzi, którego schematu uwierzytelniania http używa proxy.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.