使用node和express解压POST请求体

8

我有一个简单的node应用程序,旨在记录来自客户端的指标。

客户端使用Python的zlib模块将指标以json格式压缩发送,我正在尝试添加中间件,在express bodyParse之前解压请求帖子。

我的中间件仅仅是由express默认提供的。

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

我尝试添加一个简单的中间件来获取数据,然后解压它:

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

问题出在zlib.inflate上,我遇到了这个错误:
Error: incorrect header check

数据已经使用Python的zlib模块进行压缩:
zlib.compress(jsonString)

但似乎无论是解压缩、解缩还是解压缩gzip文件都不起作用。


你确定从zlib.unzip中没有得到“err”,因此next()没有被调用吗?如果是这种情况,请尝试将数据切换为数组。请查看此答案https://dev59.com/l2ct5IYBdhLWcg3wXsMy#12776856。另外,请确保在bodyParser之前使用您的中间件。 - Aaron
这个答案不是针对由Node完成而不是客户端完成的请求解压缩的吗? - alex88
1
无论如何,如果出现错误,您都应该调用next(err)。我建议您放弃使用bodyParser中间件,直接使用req.body = JSON.parse(buffer) - Linus Thiel
好的,问题出在解压函数上,感谢指出,我已经纠正了问题。 - alex88
2个回答

13

我自己找到了解决方案,问题出在这段代码:

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

似乎连接请求数据不正确,所以我已经将我的中间件切换为以下内容:

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

拼接缓冲区完美运作,我现在可以获取请求体解压后的数据。


如果你想知道为什么,那是因为你的第一次尝试是将原始二进制数据转换为字符串。由于UTF-8不适合保存任意字节(例如在压缩数据流中找到的字节),所以你的数据已经损坏了。默认情况下,data事件会给你一个Buffer,这是Node处理原始数据的方式。 - josh3736
@josh3736并且转换为字符串会丢失一些数据?那么这个块已经是缓冲区,我可以轻松地推送它而不是创建新的缓冲区? - alex88
是的。从data事件的文档中可以看到:如果使用request.setEncoding()设置了编码,则chunk是一个字符串,否则它是一个Buffer - josh3736
嘿,你能贴出完整的应用程序初始化代码吗?我遇到一个问题,就是inflate回调(我正在使用gunzip)时,我的结果为空。 - Tal Barda

3

我知道这是一个非常晚的回复,但是使用模块body-parser,它可以:

返回仅解析json的中间件。该解析器接受任何Unicode编码的主体,并支持gzip和deflate编码的自动膨胀。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接