如何在nodejs express项目中使用body-parser的同时获取JSON化的body和raw body

express项目中通常使用body-parser进行post参数的解析,最常用的是其中的json和urlencoded的parser,可分别对以JSON格式的post参数和urlencoeded的post参数进行解析,均可获得一个JSON化的req.body,如:

{
    "username": "user",
    "password": "pass"
}

body-parser还有一个raw parser,可以获取一个buffer对象的req.body。

通过详细阅读body-parser的源代码,可以知道,各个parser会对req headers及post参数进行一系列的判断和处理,只有满足条件的情况下才对post参数进行解析,解析之前,首先使用raw-body模块对req进行处理,其处理过程是将req作为一个readable stream进行处理,从而得到raw body内容,然后按具体的格式进行解析。

在express项目中,通常顺序调用body-parser所提供的parser,这样当一个parser无法满足post参数解析条件时,还可以使用另一个parser进行解析(在某些特殊的请求中,有可能所有parser均无法解析)。

app.use(bodyParser.raw);
app.use(bodyParser.json);
app.use(bodyParser.urlencoded({
    extended: false
});

但body-parser的各个parser在解析的过程中,若对满足解析条件的post参数进行了解析,req作为一个stream对象,已经被消耗,无法再使用另一个parser对post参数解析,也即post参数只能被第一个满足解析条件的parser进行解析。因此即使先后调用raw、json、urlencoded这三个parser,也只能得到一个body,具体格式由各parser的调用次序及post参数满足的解析条件决定。JSON化的body和raw body如同鱼与熊掌,二者不可得兼。

但在有些场合下,可能需要在解析body的同时使用raw body进行其他操作,如某些应用场景下就需要使用raw body参与签名运算以对访问者进行鉴权。

其实body-parser提供了一个办法在解析post参数的同时获取raw body,那就是在调用parser的时候传入的参数中带verify回调函数:

app.use(bodyParser.json({
    verify: function (req, res, buf, encoding) {
        req.rawBody = buf;
    }
}));
app.use(bodyParser.urlencoded({
    extended: false,
    verify: function (req, res, buf, encoding) {
        req.rawBody = buf;
    }
}));

verify参数本身是用于对请求的校验,当校验失败的时候通过抛出error来中止body-parser的解析动作,在这里被借用来实现post参数raw body的获取。

这样一来,在将post参数解析成JSON化的req.body的同时,body-parser还会将raw body赋值给req.rawBody(当然,内存也占用了两份,这是需要注意的地方,如果应用中有大数据量的POST请求,那可就要注意了)。

    原文作者:KingMario
    原文地址: https://segmentfault.com/a/1190000003061925
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞