在body-parser之前编写expression中间件来获得原始的请求体

我写了一个Express中间件来从请求中检索原始主体,并在body-parser中间件之前将其设置。

我的自定义中间件调用了req.setEncoding('utf8') ,但是这会导致下面的body-parser错误:

错误:不应该设置stream编码

 at readStream (/node_modules/body-parser/node_modules/raw-body/index.js:211:17) at getRawBody (/node_modules/body-parser/node_modules/raw-body/index.js:106:12) at read (/node_modules/body-parser/lib/read.js:76:3) at jsonParser (/node_modules/body-parser/lib/types/json.js:127:5) 

这是我的代码:

 var express = require('express'); var bodyParser = require('body-parser') function myMiddleware() { return function(req, res, next) { req.rawBody = ''; req.setEncoding('utf8'); req.on('data', function(chunk) { req.rawBody += chunk; }); req.on('end', function() { next(); }); } } var app = express(); app.use(myMiddleware()); app.use(bodyParser.json()); var listener = app.listen(3000, function() { }); app.get('/webhook/', function (req, res) { res.sendStatus(200); }); 

有没有办法来解除编码? 还有另外一种方法可以退出原始的身体,但是之后仍然使用身体parsing器吗?

你在调用next()里面的“done”,这意味着这个stream已经被使用了。 相反,设置“数据”的处理程序,然后使用next()传递请求。 “完成”事件可能在bodyParser内处理,所以执行后你可以访问req.rawBody 。 如果不是这种情况,您可以添加另一个调用req.on('done')内的next()中间件,以保留其余部分,直到获得所有数据为止。

 // custom middleware - req, res, next must be arguments on the top level function function myMiddleware(req, res, next) { req.rawBody = ''; req.on('data', function(chunk) { req.rawBody += chunk; }); // call next() outside of 'end' after setting 'data' handler next(); } // your middleware app.use(myMiddleware); // bodyparser app.use(bodyParser.json()) // test that it worked function afterMiddleware(req, res, next) { console.log(req.rawBody); next(); } app.use(afterMiddleware); 

如果你需要访问原始的身体,你可能也想看看bodyParser.raw() 。 这将把原体放入req.body ,与bodyParse.json()相同,但是可以根据内容types有条件地运行 – 检查options.type

事实certificate, 身体分析器有一个validation选项,当请求正文被读取时调用一个函数。 该函数将该主体作为缓冲区接收。

这里是一个例子:

 var express = require('express'); var bodyParser = require('body-parser') function verifyRequest() { return function(req, res, buf, encoding) { // The raw body is contained in 'buf' console.log(buf.toString('utf8')); }; } var app = express(); var listener = app.listen(3000); // Hook 'verifyRequest' with body-parser here. app.use(bodyParser.json({ verify: verifyRequest })) app.post('/webhook/', function (req, res) { res.status(200).send("done!"); }); 

我推荐一个不同的方法,因为你当前的方法实际上消耗了这个消息,并且使身体分析器不可能读取它(并且通过同时调用nextpopup一堆边缘情况错误):

 app.use(bodyParser.json()); app.use(bodyParser.text({type: '*/*'})); 

这将读取任何application/json请求作为JSON,和其他一切文本。

如果除了文本之外还必须有JSON对象,我build议您自己parsing它:

 app.use(bodyParser.text({type: '*/*'})); app.use(myMiddleware); function myMiddleware(req, res, next) { req.rawBody = req.body; if(req.headers['content-type'] === 'application/json') { req.body = JSON.parse(req.body); } next(); }