Próbuję utworzyć serwer proxy, aby przekazywać HTTP GET
żądania od klienta do witryny innej firmy (np. Google). Mój serwer proxy musi tylko odzwierciedlać przychodzące żądania do odpowiedniej ścieżki w witrynie docelowej, więc jeśli żądany adres URL mojego klienta to:
127.0.0.1/images/srpr/logo11w.png
Należy udostępnić następujący zasób:
http://www.google.com/images/srpr/logo11w.png
Oto co wymyśliłem:
http.createServer(onRequest).listen(80);
function onRequest (client_req, client_res) {
client_req.addListener("end", function() {
var options = {
hostname: 'www.google.com',
port: 80,
path: client_req.url,
method: client_req.method
headers: client_req.headers
};
var req=http.request(options, function(res) {
var body;
res.on('data', function (chunk) {
body += chunk;
});
res.on('end', function () {
client_res.writeHead(res.statusCode, res.headers);
client_res.end(body);
});
});
req.end();
});
}
Działa dobrze ze stronami html, ale w przypadku innych typów plików zwraca po prostu pustą stronę lub komunikat o błędzie z witryny docelowej (który różni się w różnych witrynach).
javascript
node.js
proxy
Nasser Torabzade
źródło
źródło
http
, zamówienie powiązanych modułów od niskiego do wysokiego abstrakcji są:node
,http
,connect
,express
zaczerpnięte z stackoverflow.com/questions/6040012/...Odpowiedzi:
Uważam, że przetwarzanie odpowiedzi otrzymanej z serwera innej firmy nie jest dobrym pomysłem. Zwiększy to tylko zużycie pamięci serwera proxy. Co więcej, jest to powód, dla którego twój kod nie działa.
Zamiast tego spróbuj przekazać odpowiedź do klienta. Rozważ następujący fragment:
var http = require('http'); http.createServer(onRequest).listen(3000); function onRequest(client_req, client_res) { console.log('serve: ' + client_req.url); var options = { hostname: 'www.google.com', port: 80, path: client_req.url, method: client_req.method, headers: client_req.headers }; var proxy = http.request(options, function (res) { client_res.writeHead(res.statusCode, res.headers) res.pipe(client_res, { end: true }); }); client_req.pipe(proxy, { end: true }); }
źródło
text/html
, w przypadku obrazów / plików PDF lub jakiejkolwiek innej treści, upewnij się, że przekazujesz prawidłowe nagłówki. Będę mógł zaoferować więcej pomocy, jeśli podzielisz się modyfikacjami zastosowanymi w odpowiedziach.Oto implementacja wykorzystująca
node-http-proxy
od nodejitsu.var http = require('http'); var httpProxy = require('http-proxy'); var proxy = httpProxy.createProxyServer({}); http.createServer(function(req, res) { proxy.web(req, res, { target: 'http://www.google.com' }); }).listen(3000);
źródło
Oto serwer proxy używający żądania, które obsługuje przekierowania. Użyj go, naciskając adres URL serwera proxy http://domain.com:3000/?url=[twoj_url]
var http = require('http'); var url = require('url'); var request = require('request'); http.createServer(onRequest).listen(3000); function onRequest(req, res) { var queryData = url.parse(req.url, true).query; if (queryData.url) { request({ url: queryData.url }).on('error', function(e) { res.end(e); }).pipe(res); } else { res.end("no url found"); } }
źródło
res.end(e);
spowodujeTypeError [ERR_INVALID_ARG_TYPE]: The "chunk" argument must be of type string or an instance of Buffer. Received an instance of Error
Super prosty i czytelny, oto jak utworzyć lokalny serwer proxy na lokalnym serwerze HTTP za pomocą samego Node.js (testowane w wersji 8.1.0 ). Uważam, że jest to szczególnie przydatne do testowania integracji, więc oto mój udział:
/** * Once this is running open your browser and hit http://localhost * You'll see that the request hits the proxy and you get the HTML back */ 'use strict'; const net = require('net'); const http = require('http'); const PROXY_PORT = 80; const HTTP_SERVER_PORT = 8080; let proxy = net.createServer(socket => { socket.on('data', message => { console.log('---PROXY- got message', message.toString()); let serviceSocket = new net.Socket(); serviceSocket.connect(HTTP_SERVER_PORT, 'localhost', () => { console.log('---PROXY- Sending message to server'); serviceSocket.write(message); }); serviceSocket.on('data', data => { console.log('---PROXY- Receiving message from server', data.toString(); socket.write(data); }); }); }); let httpServer = http.createServer((req, res) => { switch (req.url) { case '/': res.writeHead(200, {'Content-Type': 'text/html'}); res.end('<html><body><p>Ciao!</p></body></html>'); break; default: res.writeHead(404, {'Content-Type': 'text/plain'}); res.end('404 Not Found'); } }); proxy.listen(PROXY_PORT); httpServer.listen(HTTP_SERVER_PORT);
https://gist.github.com/fracasula/d15ae925835c636a5672311ef584b999
źródło
Twój kod nie działa w przypadku plików binarnych, ponieważ nie można ich rzutować na ciągi w module obsługi zdarzeń danych. Jeśli chcesz manipulować plikami binarnymi, musisz użyć bufora . Przepraszam, nie mam przykładu użycia bufora, ponieważ w moim przypadku potrzebowałem manipulować plikami HTML. Po prostu sprawdzam typ zawartości, a następnie pliki tekstowe / html aktualizuję w razie potrzeby:
app.get('/*', function(clientRequest, clientResponse) { var options = { hostname: 'google.com', port: 80, path: clientRequest.url, method: 'GET' }; var googleRequest = http.request(options, function(googleResponse) { var body = ''; if (String(googleResponse.headers['content-type']).indexOf('text/html') !== -1) { googleResponse.on('data', function(chunk) { body += chunk; }); googleResponse.on('end', function() { // Make changes to HTML files when they're done being read. body = body.replace(/google.com/gi, host + ':' + port); body = body.replace( /<\/body>/, '<script src="http://localhost:3000/new-script.js" type="text/javascript"></script></body>' ); clientResponse.writeHead(googleResponse.statusCode, googleResponse.headers); clientResponse.end(body); }); } else { googleResponse.pipe(clientResponse, { end: true }); } }); googleRequest.end(); });
źródło
Oto bardziej zoptymalizowana wersja powyższej odpowiedzi Mike'a, która poprawnie pobiera typ zawartości witryn, obsługuje żądania POST i GET oraz używa agenta użytkownika przeglądarki, aby witryny mogły identyfikować serwer proxy jako przeglądarkę. Możesz po prostu ustawić adres URL, zmieniając,
url =
a on automatycznie ustawi HTTP i HTTPS bez robienia tego ręcznie.var express = require('express') var app = express() var https = require('https'); var http = require('http'); const { response } = require('express'); app.use('/', function(clientRequest, clientResponse) { var url; url = 'https://www.google.com' var parsedHost = url.split('/').splice(2).splice(0, 1).join('/') var parsedPort; var parsedSSL; if (url.startsWith('https://')) { parsedPort = 443 parsedSSL = https } else if (url.startsWith('http://')) { parsedPort = 80 parsedSSL = http } var options = { hostname: parsedHost, port: parsedPort, path: clientRequest.url, method: clientRequest.method, headers: { 'User-Agent': clientRequest.headers['user-agent'] } }; var serverRequest = parsedSSL.request(options, function(serverResponse) { var body = ''; if (String(serverResponse.headers['content-type']).indexOf('text/html') !== -1) { serverResponse.on('data', function(chunk) { body += chunk; }); serverResponse.on('end', function() { // Make changes to HTML files when they're done being read. body = body.replace(`example`, `Cat!` ); clientResponse.writeHead(serverResponse.statusCode, serverResponse.headers); clientResponse.end(body); }); } else { serverResponse.pipe(clientResponse, { end: true }); clientResponse.contentType(serverResponse.headers['content-type']) } }); serverRequest.end(); }); app.listen(3000) console.log('Running on 0.0.0.0:3000')
źródło
Właśnie napisałem proxy w nodejs, które zajmuje się HTTPS z opcjonalnym dekodowaniem wiadomości. Ten serwer proxy może również dodać nagłówek uwierzytelniania proxy, aby przejść przez korporacyjny serwer proxy. Musisz podać jako argument adres URL, aby znaleźć plik proxy.pac i skonfigurować użycie korporacyjnego serwera proxy.
https://github.com/luckyrantanplan/proxy-to-proxy-https
źródło