Unzip POST body with node + express

2020-05-21 05:46发布

问题:

I've a simple node app that should write metrics from clients. Clients send metrics in json format zipped with python's zlib module, I'm trying to add a middleware to unzip the request post before the express bodyParse takes place.

My middlewares are simply the ones provided by express by default:

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

I've tried to add a simple middleware that gets the data and then unzips it:

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

The problem is with zlib.inflate I get this error:

Error: incorrect header check

The data has been compressed with python's zlib module:

zlib.compress(jsonString)

but seems that neither unzip, inflate, gunzip works.

回答1:

Found the solution on my own, the problem was with this piece of code:

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

seems that concatenating request data isn't correct, so I've switched my middleware to this:

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

concatenating buffers works perfectly and I'm now able to get request body decompressed.



回答2:

I know this is a very late response, but with module body-parser, it will:

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