2012-11-20 15 views
12

Cercando di saperne di più su node.js creando un semplice server proxy http. Lo scenario di utilizzo è semplice: utente -> proxy -> server -> proxy -> utenteSemplice proxy node.js mediante piping del server http alla richiesta http

Il codice seguente funziona fino all'ultimo passaggio. Impossibile trovare il modo di reindirizzare l'output del connettore all'utente.

#!/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 
}); 

Utilizzando tcpflow vedo la richiesta in ingresso dal browser, allora la richiesta proxy in uscita, quindi la risposta del server indietro al proxy. In qualche modo non sono riuscito a ritrasmettere la risposta al browser.

Qual è il modo corretto di implementare questa logica con i tubi?

risposta

19

OK. Fatto.

AGGIORNAMENTO: NB! Come riportato nei commenti, questo esempio non funziona più. Molto probabilmente a causa del cambiamento Streams2 API (nodo 0.9+)

Piping al client deve accadere callback di connettore all'interno come segue:

#!/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(); 
}); 
+0

-1 perché: stream.js: 94 laterale er; // Errore di flusso non gestito nella pipe. ^ errore: collegare ECONNREFUSED a errnoException (net.js: 901: 11) a Object.afterConnect [come onComplete] (net.js: 892: 19) –

+3

@ Rob, molto probabilmente questo esempio non funziona con la nuova API Streams2. Gli stream2 sono stati introdotti come beta nel nodo 0.9 e sono diventati stabili nel ramo 0.10. 0,10 è stato rilasciato marzo 2013 - mesi dopo questa discussione. Quindi, se vuoi davvero essere più costruttivo, invece di inserire -1, adattare l'esempio per la nuova API. –

+0

@NikolaiGorchilov L'esempio precedente ha funzionato per me con il nodo 0.10.13. Solo il cambiamento che ho dovuto fare è 'response.writeHead' invece di' response.writeHeader' – Gireesh

19

non dovete 'pausa', solo 'pipe' è ok

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

la richiesta http non finirà fino a quando non lo dirai "fine";

+4

{end: true} è un bel suggerimento. 10x. Per quanto riguarda la pausa, continuo a pensare che sia meglio usarlo. Immagina un utente che carica un file di grandi dimensioni con HTTP POST. Perché il suo file viene bufferizzato nella RAM del server mentre la connessione in uscita è in costruzione? E se questa connessione in uscita non fosse possibile per un motivo o per un altro? –

+1

FWIW, '{end: true}' non è più necessario con il nodo moderno - l'impostazione predefinita è 'true', quindi è necessario passare solo le opzioni se si sta disabilitando. – Jesse

1

Ho utilizzato gli esempi da questo post per le richieste http/s proxy. Di fronte al problema che i cookie sono stati persi da qualche parte.

Quindi per risolvere il problema è necessario gestire le intestazioni dalla risposta proxy.

Sotto l'esempio di lavoro:

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