【发布时间】:2013-09-13 15:35:55
【问题描述】:
当我使用 Express 时,我的代码是:
app.use(express.bodyParser());
我如何获得原始请求正文?
【问题讨论】:
-
Expressjs raw body的可能重复
当我使用 Express 时,我的代码是:
app.use(express.bodyParser());
我如何获得原始请求正文?
【问题讨论】:
使用
app.use(express.json());
或
app.use(express.text());
或
app.use(express.urlencoded());
取决于您的原始格式
【讨论】:
// Change the way body-parser is used
const bodyParser = require('body-parser');
var rawBodySaver = function (req, res, buf, encoding) {
if (buf && buf.length) {
req.rawBody = buf.toString(encoding || 'utf8');
}
}
app.use(bodyParser.json({ verify: rawBodySaver, extended: true }));
// Now we can access raw-body any where in out application as follows
request.rawBody;
【讨论】:
编辑 2: 正文解析器模块的 1.15.2 版引入了 raw mode,它将正文作为 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'
};
如果您希望原始解析器解析 application/octet-stream 以外的其他 MIME 类型,则需要在此处进行更改。它还将支持通配符匹配,例如*/* 或*/application。
注意:以下答案适用于 Express 4 之前的版本,其中中间件仍与框架捆绑在一起。现代等效的是body-parser 模块,必须单独安装。
Express 中的rawBody 属性曾经可用,但自版本 1.5.1 起已删除。要获取原始请求正文,您必须在使用 bodyParser 之前放入一些中间件。你也可以阅读关于它的 GitHub 讨论here。
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 解析器的 line 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.
【讨论】:
使用body-parser 解析正文:
app.use(bodyParser.text());
app.use(bodyParser.urlencoded());
app.use(bodyParser.raw());
app.use(bodyParser.json());
即。如果您应该获取原始文本文件,请运行.text()。
这就是 body-parser 目前支持的
【讨论】:
这个解决方案对我有用:
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) { }); 的解决方案时,它不适用于分块的请求正文。
【讨论】:
我得到了一个与 bodyParser 配合得很好的解决方案,在 bodyParser 中使用 verify 回调。在这段代码中,我使用它来获取内容的 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 的新手(从字面上看是昨天开始的!),所以我想听听 cmets 对这个解决方案的看法。
【讨论】:
req.rawBody = buf.toString(); 并将其余部分从verify 函数中取出,因为这就是我所需要的,而且它工作得很好。无需更改 bodyParser 源代码!
req.rawBody = buf.toString(encoding);
application/json 请求
请注意其他答案,因为如果您希望还支持 json、urlencoded 等,它们将无法与 bodyParser 一起正常播放。要使其与 bodyParser 一起使用,您应该将处理程序设置为仅在 @987654321 上注册@ header(s) 你关心的,就像 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());
【讨论】: