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?
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?
Odpowiedzi:
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.
404
, a serwer docelowy nigdy nie otrzymuje żądania.
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);
}
})
http
i https
w moim przypadku, wielkie dzięki
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);
});
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);
});
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
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()
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
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”.
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();
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"
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.');
}
});
Myślę, że istnieje lepsza alternatywa dla odpowiedzi z 2019 roku. Możemy użyć global-tunnel-ng
pakietu do zainicjowania proxy i nie zanieczyszczać kodu http
lub https
opartego na nim wszędzie. Więc najpierw zainstaluj global-tunnel-ng
pakiet:
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
});
Może nie być dokładnie tym, na co liczyłeś, ale możesz rzucić okiem na http://github.com/nodejitsu/node-http-proxy, ponieważ może to rzucić trochę światła na sposób korzystania z aplikacji z protokołem http. Klient.
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.
Aby skorzystać z proxy z https, wypróbowałem rady na tej stronie (używając zależności https-proxy-agent ) i zadziałało:
http://codingmiles.com/node-js-making-https-request-via-proxy/
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)=>{...});
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.