2013-01-07 8 views
6

Ho una semplice applicazione di nodo che dovrebbe scrivere le metriche dai client. I client inviano metriche in formato json compresso con il modulo zlib di python, sto cercando di aggiungere un middleware per decomprimere il post di richiesta prima che venga eseguito express bodyParse.Decomprimere il corpo POST con il nodo + express

mie middleware sono semplicemente quelli forniti da espresso per impostazione predefinita:

app.configure(function(){ 
    app.set('port', process.env.PORT || 3000); 
    app.set('views', __dirname + '/views'); 
    app.set('view engine', 'jade'); 
    app.use(express.favicon()); 
    app.use(express.logger('dev')); 
    app.use(express.bodyParser()); 
    app.use(express.methodOverride()); 
    app.use(express.cookieParser('your secret here')); 
    app.use(express.session()); 
    app.use(app.router); 
    app.use(require('less-middleware')({ src: __dirname + '/public' })); 
    app.use(express.static(path.join(__dirname, 'public'))); 
}); 

ho cercato di aggiungere un semplice middleware che ottiene i dati e quindi apre la chiusura lampo è:

app.use(function(req, res, next) { 
    var data = ''; 
    req.addListener("data", function(chunk) { 
     data += chunk; 
    }); 

    req.addListener("end", function() { 
     zlib.inflate(data, function(err, buffer) { 
      if (!err) { 
       req.body = buffer; 
       next(); 
      } else { 
       next(err); 
      } 
     }); 
    }); 
}); 

Il problema è con zlib.inflate ottengo questo errore:

Error: incorrect header check 

I dati sono stati compressi con modulo zlib di python:

zlib.compress(jsonString) 

ma sembra che non decomprimere, gonfiare, gunzip funziona.

+0

Sei sicuro non si ottiene un "ERR" dal zlib.unzip e di conseguenza il prossimo() non viene chiamato? Se questo è il caso, prova a cambiare i dati in un array. Dai un'occhiata a questa risposta http://stackoverflow.com/a/12776856/30763 Inoltre assicurati che il tuo middleware sia utilizzato prima di bodyParser. – Aaron

+0

Quella risposta non è per decomprimere una richiesta fatta dal nodo e non dal client? – alex88

+1

@ alex88 in ogni caso, dovresti chiamare 'next (err)' se c'è un errore. Suggerisco anche di rinunciare al middleware 'bodyParser' e di eseguire direttamente' req.body = JSON.parse (buffer) '. –

risposta

12

trovato la soluzione per conto mio, il problema era con questo pezzo di codice:

req.addListener("data", function(chunk) { 
    data += chunk; 
}); 

sembra che concatenando richiesta di dati non è corretto, così ho acceso il mio middleware a questo:

app.use(function(req, res, next) { 
    var data = []; 
    req.addListener("data", function(chunk) { 
     data.push(new Buffer(chunk)); 
    }); 
    req.addListener("end", function() { 
     buffer = Buffer.concat(data); 
     zlib.inflate(buffer, function(err, result) { 
      if (!err) { 
       req.body = result.toString(); 
       next(); 
      } else { 
       next(err); 
      } 
     }); 
    }); 
}); 

concatenare i buffer funziona perfettamente e ora sono in grado di ottenere il corpo della richiesta decompresso.

+0

Nel caso ti stia chiedendo * perché *, è perché il tuo primo tentativo è stato convertire i dati binari non elaborati in una stringa. Poiché UTF-8 non è pensato per contenere byte arbitrari (come quelli che dovresti trovare in un flusso di dati compresso), i tuoi dati sono stati corrotti. Per impostazione predefinita, l'evento ['data'] (http://nodejs.org/api/http.html#http_event_data) ti dà un [' Buffer'] (http://nodejs.org/api/buffer.html# buffer_buffer), che è il modo in cui Node gestisce i dati grezzi. – josh3736

+0

@ josh3736 e la conversione in stringa stava perdendo alcuni dati? Quindi il chunk è già un Buffer e posso facilmente spingerlo invece di creare un nuovo Buffer? – alex88

+0

[Sì. Dai documenti per l'evento 'data':] (http://nodejs.org/api/http.html#http_event_data)" * Il 'chunk' è una stringa se una codifica è stata impostata con' request.setEncoding() ', altrimenti è un' Buffer'. * " – josh3736

1

So che questa è una risposta molto tardi, ma con modulo body-parser, sarà:

Returns middleware that only parses json. This parser accepts any Unicode encoding of the body and supports automatic inflation of gzip and deflate encodings.

var bodyParser = require('body-parser'); 
app.use(bodyParser.json());  // to support JSON-encoded bodies