web-dev-qa-db-fra.com

Proxy node.js simple en canalisant le serveur http vers une requête http

Essayez d’en savoir plus sur node.js en créant un simple serveur proxy http. Le scénario d'utilisation est simple: utilisateur -> proxy -> serveur -> proxy -> utilisateur

Le code suivant fonctionne jusqu'à la dernière étape. Impossible de trouver le moyen de rediriger la sortie du connecteur vers l'utilisateur.

#!/usr/bin/env node

var
    url = require('url'),
    http = require('http'),
    acceptor = http.createServer().listen(3128);

acceptor.on('request', function(request, response) {
    console.log('request ' + request.url);
    request.pause();
    var options = url.parse(request.url);
    options.headers = request.headers;
    options.method = request.method;
    options.agent = false;

    var connector = http.request(options);
    request.pipe(connector);
    request.resume();
//  connector.pipe(response); // doesn't work
//  connector.pipe(request); // doesn't work either
});

En utilisant tcpflow, je vois la requête entrante du navigateur, puis la requête proxy sortante, puis la réponse du serveur au proxy. D'une manière ou d'une autre, je n'ai pas réussi à retransmettre la réponse au navigateur.

Quelle est la bonne façon de mettre en œuvre cette logique avec des tubes?

13
Nikolai Gorchilov

vous n'avez pas à "mettre en pause", juste "pipe" est ok 

var connector = http.request(options, function(res) {
  res.pipe(response, {end:true});//tell 'response' end=true
});
request.pipe(connector, {end:true});

la requête http ne se terminera pas tant que vous n’aurez pas dit qu’elle est 'end';

22
Jay

D'ACCORD. Je l'ai.

MISE À JOUR: NB! Comme indiqué dans les commentaires, cet exemple ne fonctionne plus. Très probablement en raison du changement de l'API Streams2 (noeud 0.9+)

La redirection vers le client doit s'effectuer à l'intérieur du rappel du connecteur, comme suit:

#!/usr/bin/env node

var
    url = require('url'),
    http = require('http'),
    acceptor = http.createServer().listen(3128);

acceptor.on('request', function(request, response) {
    console.log('request ' + request.url);
    request.pause();
    var options = url.parse(request.url);
    options.headers = request.headers;
    options.method = request.method;
    options.agent = false;

    var connector = http.request(options, function(serverResponse) {
            serverResponse.pause();
            response.writeHeader(serverResponse.statusCode, serverResponse.headers);
            serverResponse.pipe(response);
            serverResponse.resume();
    });
    request.pipe(connector);
    request.resume();
});
22
Nikolai Gorchilov

J'ai utilisé les exemples de ce post pour proxy les requêtes http/s. Face au problème que les cookies ont été perdus quelque part.

Donc, pour résoudre ce problème, vous devez gérer les en-têtes de la réponse du proxy. 

Ci-dessous l'exemple de travail:

req = service.request(options, function(res) {
    response.writeHead(res.statusCode, res.headers);
    return res.pipe(response, {end: true});
});
request.pipe(req, {end: true});
1
kashesandr