Como criar um proxy http simples no nó.js?

estou a tentar criar um servidor proxy para passar HTTP GET pedidos de um cliente para um site de terceiros (diz google). O meu 'proxy' só precisa de espelhar os pedidos de entrada para o seu caminho correspondente no site de destino, por isso, se o url pedido do meu cliente for:

127.0.0.1/images/srpr/logo11w.png

deve ser servido o seguinte recurso:

http://www.google.com/images/srpr/logo11w.png
Eis o que descobri:
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: 'GET'
        };
        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();
    });
}

ele funciona bem com páginas html, mas para outros tipos de arquivos, ele apenas retorna uma página em branco ou alguma mensagem de erro de local de destino (que varia em diferentes locais).

Author: shabunc, 2013-12-03

6 answers

Acho que não é boa ideia processar a resposta recebida do servidor da terceira parte. Isto só irá aumentar a pegada de memória do seu servidor proxy. Além disso, é a razão pela qual o seu código não está a funcionar. Em vez disso, tenta passar a resposta para o cliente. Considere o seguinte excerto:
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: 'GET'
  };

  var proxy = http.request(options, function (res) {
    res.pipe(client_res, {
      end: true
    });
  });

  client_req.pipe(proxy, {
    end: true
  });
}
 67
Author: vmx, 2013-12-03 15:05:31
Aqui está uma implementação usando node-http-proxy do 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);
 14
Author: bosgood, 2016-09-05 13:29:24

Aqui está um servidor proxy usando pedido que lida com redirecionamentos. Use-o carregando no URL do seu '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");
    }
}
 8
Author: Henry, 2014-12-15 04:33:40

O seu código não funciona para ficheiros binários porque não podem ser moldados para cadeias de caracteres no controlador de eventos de dados. Se precisar de manipular ficheiros binários, terá de usar um buffer. Desculpe, eu não tenho um exemplo de usar um buffer porque no meu caso eu precisava manipular arquivos HTML. Basta verificar o tipo de Conteúdo e, em seguida, para arquivos texto/html atualizá-los conforme necessário:

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();
});    
 3
Author: Mike Dilorenzo, 2014-12-02 23:46:55

Super Simples e legível, aqui está como você cria um servidor proxy local para um Servidor HTTP local com apenas um nó.js (testado em v8.1.0). Achei-o particularmente útil para testes de integração, por isso, aqui está a minha 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

 1
Author: Francesco Casula, 2017-06-23 17:03:52

Eu apenas escrevi um proxy em notejs que cuidam de HTTPS com decodificação opcional da mensagem. Este proxy também pode adicionar cabeçalho proxy-authentification, a fim de passar por um proxy corporativo. Você precisa dar como argumento a url para encontrar o proxy.pac file, a fim de configurar o uso do proxy corporativo.

Https://github.com/luckyrantanplan/proxy-to-proxy-https

 0
Author: Florian Prud'homme, 2016-10-26 17:09:33