当我使用Express时,我的代码是:
app.use(express.bodyParser());
我将如何获得原始请求正文?
Answers:
编辑2:正文解析器模块的1.15.2版引入了原始模式,该模式将正文作为Buffer返回。默认情况下,它还会自动处理deflate和gzip解压缩。用法示例:
var bodyParser = require('body-parser');
app.use(bodyParser.raw(options));
app.get(path, function(req, res) {
// req.body is a Buffer object
});
默认情况下,该options
对象具有以下默认选项:
var options = {
inflate: true,
limit: '100kb',
type: 'application/octet-stream'
};
如果您希望原始解析器解析以外的其他MIME类型application/octet-stream
,则需要在此处进行更改。它还将支持通配符匹配,例如*/*
或*/application
。
注意:以下答案适用于Express 4之前的版本,其中中间件仍与框架捆绑在一起。现代等效项是主体解析器模块,必须单独安装。
rawBody
Express中的属性曾经可用,但是从版本1.5.1开始被删除。要获取原始请求主体,必须在使用bodyParser之前放入一些中间件。您还可以在此处阅读有关GitHub的讨论。
app.use(function(req, res, next) {
req.rawBody = '';
req.setEncoding('utf8');
req.on('data', function(chunk) {
req.rawBody += chunk;
});
req.on('end', function() {
next();
});
});
app.use(express.bodyParser());
该中间件将从实际数据流中读取,并将其存储在rawBody
请求的属性中。然后,您可以像这样访问原始主体:
app.post('/', function(req, res) {
// do something with req.rawBody
// use req.body for the parsed body
});
编辑:似乎此方法和bodyParser拒绝共存,因为一个方法将在另一个方法之前消耗请求流,从而导致第二个方法永远不会触发end
,从而永远不会调用next()
,并挂起您的应用程序。
最简单的解决方案很可能是修改bodyParser的源,您可以在Connect的JSON解析器的第57行中找到该源。这就是修改后的版本。
var buf = '';
req.setEncoding('utf8');
req.on('data', function(chunk){ buf += chunk });
req.on('end', function() {
req.rawBody = buf;
var first = buf.trim()[0];
...
});
您可以在以下位置找到文件:
/node_modules/express/node_modules/connect/lib/middleware/json.js
。
使用bodyParser中的verify
回调,我得到了一个与bodyParser配合良好的解决方案。在这段代码中,我正在使用它来获取内容的sha1并获取原始内容。
app.use(bodyParser.json({
verify: function(req, res, buf, encoding) {
// sha1 content
var hash = crypto.createHash('sha1');
hash.update(buf);
req.hasha = hash.digest('hex');
console.log("hash", req.hasha);
// get rawBody
req.rawBody = buf.toString();
console.log("rawBody", req.rawBody);
}
}));
我是Node.js和express.js的新手(从昨天开始,从字面上看!),所以我想听听对此解决方案的评论。
req.rawBody = buf.toString();
将其余部分包括在内,并从verify
功能中删除了其余部分,因为这是我所需要的,并且运行良好。无需更改bodyParser源代码!
req.rawBody = buf.toString(encoding);
application/json
请求
此解决方案为我工作:
var rawBodySaver = function (req, res, buf, encoding) {
if (buf && buf.length) {
req.rawBody = buf.toString(encoding || 'utf8');
}
}
app.use(bodyParser.json({ verify: rawBodySaver }));
app.use(bodyParser.urlencoded({ verify: rawBodySaver, extended: true }));
app.use(bodyParser.raw({ verify: rawBodySaver, type: '*/*' }));
当我使用解决方案req.on('data', function(chunk) { });
不能在分块的请求正文上工作时。
请谨慎处理其他答案,因为如果您还希望支持json,urlencoded等,它们将无法在bodyParser上正常播放。要使其与bodyParser一起使用,您应限制您的处理程序仅在 Content-Type
标头上就像bodyParser本身一样关心。
为了得到一个请求的原始主体内容Content-Type: "text/plain"
到req.rawBody
你可以这样做:
app.use(function(req, res, next) {
var contentType = req.headers['content-type'] || ''
, mime = contentType.split(';')[0];
if (mime != 'text/plain') {
return next();
}
var data = '';
req.setEncoding('utf8');
req.on('data', function(chunk) {
data += chunk;
});
req.on('end', function() {
req.rawBody = data;
next();
});
});
app.use(bodyParser.urlencoded({limit: '80mb', extended: true})); app.use(bodyParser.json({limit: '80mb'})); app.use(bodyParser.raw({type: 'application/octet-stream'}))
这也可以。
这是上述六氰化物答案的一种变化。该中间件还处理“数据”事件,但在调用“下一个”之前不等待数据被消耗。这样,中间件和bodyParser可以共存,并行使用流。
app.use(function(req, res, next) {
req.rawBody = '';
req.setEncoding('utf8');
req.on('data', function(chunk) {
req.rawBody += chunk;
});
next();
});
app.use(express.bodyParser());
使用body-parser解析物体的形状:
app.use(bodyParser.text());
app.use(bodyParser.urlencoded());
app.use(bodyParser.raw());
app.use(bodyParser.json());
即。如果您应该获取原始文本文件,请运行.text()
。
那就是body-parser当前支持的功能