Estoy tratando de crear un servidor proxy para pasar HTTP GET
solicitudes de un cliente a un sitio web de terceros (digamos Google). Mi proxy solo necesita reflejar las solicitudes entrantes en su ruta correspondiente en el sitio de destino, por lo que si la URL solicitada por mi cliente es:
127.0.0.1/images/srpr/logo11w.png
Se debe servir el siguiente recurso:
http://www.google.com/images/srpr/logo11w.png
Esto es lo que se me ocurrió:
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();
});
}
Funciona bien con páginas html, pero para otros tipos de archivos, solo devuelve una página en blanco o algún mensaje de error del sitio de destino (que varía en diferentes sitios).
javascript
node.js
proxy
Nasser Torabzade
fuente
fuente
http
, una orden de módulos relacionados de menor a mayor abstracción son:node
,http
,connect
,express
tomada de stackoverflow.com/questions/6040012/...Respuestas:
No creo que sea una buena idea procesar la respuesta recibida del servidor de terceros. Esto solo aumentará la huella de memoria de su servidor proxy. Además, es la razón por la que su código no funciona.
En su lugar, intente transmitir la respuesta al cliente. Considere el siguiente fragmento:
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 }); }
fuente
text/html
, para imágenes / PDF o cualquier otro contenido, asegúrate de pasar los encabezados correctos. Podré ofrecer más ayuda si comparte las modificaciones que aplica a las respuestas.Aquí hay una implementación usando
node-http-proxy
de 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);
fuente
Aquí hay un servidor proxy que usa una solicitud que maneja las redirecciones. Úselo presionando la URL de su proxy 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"); } }
fuente
res.end(e);
causará unTypeError [ERR_INVALID_ARG_TYPE]: The "chunk" argument must be of type string or an instance of Buffer. Received an instance of Error
Súper simple y legible, así es como se crea un servidor proxy local en un servidor HTTP local con solo Node.js (probado en v8.1.0 ). Lo encontré particularmente útil para las pruebas de integración, así que aquí está mi parte:
/** * 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
fuente
Su código no funciona para archivos binarios porque no se pueden convertir en cadenas en el controlador de eventos de datos. Si necesita manipular archivos binarios, deberá usar un búfer . Lo siento, no tengo un ejemplo de uso de un búfer porque en mi caso necesitaba manipular archivos HTML. Solo verifico el tipo de contenido y luego los archivos de texto / html los actualizo según sea necesario:
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(); });
fuente
Aquí hay una versión más optimizada de la respuesta de Mike anterior que obtiene el tipo de contenido de los sitios web correctamente, admite solicitudes POST y GET y usa el agente de usuario de su navegador para que los sitios web puedan identificar su proxy como un navegador. Simplemente puede configurar la URL cambiando
url =
y automáticamente configurará HTTP y HTTPS sin hacerlo manualmente.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')
fuente
Juste escribí un proxy en nodejs que se encarga de HTTPS con decodificación opcional del mensaje. Este proxy también puede agregar un encabezado de autenticación de proxy para pasar por un proxy corporativo. Debe proporcionar como argumento la URL para encontrar el archivo proxy.pac para configurar el uso del proxy corporativo.
https://github.com/luckyrantanplan/proxy-to-proxy-https
fuente