Я пытаюсь создать прокси-сервер для передачи HTTP GET
запросов от клиента на сторонний веб-сайт (например, Google). Моему прокси просто нужно отражать входящие запросы по соответствующему пути на целевом сайте, поэтому, если запрашиваемый моим клиентом URL-адрес:
127.0.0.1/images/srpr/logo11w.png
Необходимо обслуживать следующий ресурс:
http://www.google.com/images/srpr/logo11w.png
Вот что я придумал:
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();
});
}
Он хорошо работает со страницами html, но для других типов файлов он просто возвращает пустую страницу или сообщение об ошибке с целевого сайта (которое зависит от разных сайтов).
javascript
node.js
proxy
Насер Торабзаде
источник
источник
http
, порядок связанных модулей от низкой до высокой абстракции:node
,http
,connect
,express
взяты из stackoverflow.com/questions/6040012/...Ответы:
Я не думаю, что будет хорошей идеей обрабатывать ответ, полученный от стороннего сервера. Это только увеличит объем памяти вашего прокси-сервера. Кроме того, это причина того, что ваш код не работает.
Вместо этого попробуйте передать ответ клиенту. Рассмотрим следующий фрагмент:
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 }); }
источник
text/html
для изображений / PDF-файлов или любого другого содержимого тип содержимого обеспечивает передачу правильных заголовков. Я смогу предложить дополнительную помощь, если вы поделитесь, какие изменения вы вносите в ответы.Вот реализация, использующая
node-http-proxy
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);
источник
Вот прокси-сервер, использующий запрос, который обрабатывает перенаправления. Используйте его, нажав URL-адрес вашего прокси http://domain.com:3000/?url=[your_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"); } }
источник
res.end(e);
вызоветTypeError [ERR_INVALID_ARG_TYPE]: The "chunk" argument must be of type string or an instance of Buffer. Received an instance of Error
Супер простой и понятный, вот как вы создаете локальный прокси-сервер для локального HTTP-сервера с помощью только Node.js (проверено на v8.1.0 ). Я нашел его особенно полезным для интеграционного тестирования, так что вот моя доля:
/** * 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
источник
Ваш код не работает для двоичных файлов, потому что они не могут быть преобразованы в строки в обработчике событий данных. Если вам нужно манипулировать двоичными файлами, вам понадобится буфер . К сожалению, у меня нет примера использования буфера, потому что в моем случае мне нужно было манипулировать файлами HTML. Я просто проверяю тип содержимого, а затем обновляю текстовые / html-файлы по мере необходимости:
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(); });
источник
Вот более оптимизированная версия ответа Майка выше, которая правильно получает Content-Type веб-сайтов, поддерживает запросы POST и GET и использует User-Agent вашего браузера, чтобы веб-сайты могли идентифицировать ваш прокси как браузер. Вы можете просто установить URL-адрес, изменив
url =
его, и он автоматически установит параметры HTTP и HTTPS, не делая этого вручную.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')
источник
Я juste написал прокси-сервер в nodejs, который заботится о HTTPS с дополнительным декодированием сообщения. Этот прокси-сервер также может добавлять заголовок прокси-аутентификации, чтобы проходить через корпоративный прокси. Вам необходимо указать в качестве аргумента URL-адрес для поиска файла proxy.pac, чтобы настроить использование корпоративного прокси.
https://github.com/luckyrantanplan/proxy-to-proxy-https
источник