web-dev-qa-db-fra.com

Comment créer un proxy http simple dans node.js?

J'essaie de créer un serveur proxy pour passer HTTP GET demandes d’un client à un site Web tiers (par exemple Google). Mon mandataire doit simplement mettre en miroir les demandes entrantes dans le chemin correspondant sur le site cible. Par conséquent, si l'URL demandée par mon client est:

127.0.0.1/images/srpr/logo11w.png

la ressource suivante devrait être servie:

http://www.google.com/images/srpr/logo11w.png

voici ce que je suis venu avec:

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();
    });
}

cela fonctionne bien avec les pages html, mais pour les autres types de fichiers, il ne renvoie qu'une page vierge ou un message d'erreur du site cible (qui varie selon les sites).

59
Nasser Torabzade

Je ne pense pas que ce soit une bonne idée de traiter les réponses reçues du serveur tiers. Cela ne fera qu'augmenter l'encombrement de la mémoire de votre serveur proxy. De plus, c'est la raison pour laquelle votre code ne fonctionne pas.

Essayez plutôt de transmettre la réponse au client. Pensez à l'extrait suivant:

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
  });
}
78
vmx

Voici une implémentation utilisant 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);
21
bosgood

Voici un serveur proxy utilisant request qui gère les redirections. Utilisez-le en tapant votre URL de 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");
    }
}
10
Henry

Votre code ne fonctionne pas pour les fichiers binaires car ils ne peuvent pas être convertis en chaînes dans le gestionnaire d'événements de données. Si vous avez besoin de manipuler des fichiers binaires, vous devez utiliser un tampon . Désolé, je n'ai pas d'exemple d'utilisation de tampon car, dans mon cas, je devais manipuler des fichiers HTML. Je vérifie simplement le type de contenu, puis pour les fichiers texte/html, mettez-les à jour si nécessaire:

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();
});    
4
Mike Dilorenzo

Super simple et lisible, voici comment créer un serveur proxy local sur un serveur HTTP local avec juste Node.js (testé sur v8.1.0 ). Je l'ai trouvé particulièrement utile pour les tests d'intégration, alors voici ma part:

/**
 * 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

2
Francesco Casula

Je viens d’écrire un proxy dans nodejs qui s’occupe de HTTPS avec décodage optionnel du message. Ce proxy peut également ajouter un en-tête d'authentification de proxy afin de passer par un proxy d'entreprise. Vous devez donner comme argument l'URL pour trouver le fichier proxy.pac afin de configurer l'utilisation du proxy d'entreprise.

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

0
Florian Prud'homme