如何使用 `bodyParser.raw()` 获取原始请求体?

14

我正在使用 Express 创建一个Web API。 该功能是允许API用户向服务器发送文件。

这是我的应用程序设置代码:

var express = require('express');
var path = require('path');
// ...
var bodyParser = require('body-parser');

var routes = require('./routes/index');
var users = require('./routes/users');

// API routes
var images = require('./routes/api/img');

var app = express();

app.use(bodyParser.raw());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);
app.use('/api', images);

// ...

module.exports = app;
请注意,我正在使用app.use(bodyParser.raw());。 如何从POST请求中获取原始字节?
const express = require('express');
const router = express.Router();

/* POST api/img */
router.post('/img', function(req, res, next) {

  // how do I get the raw bytes?

});

module.exports = router;

请考虑缩小您的代码示例,仅包含与您问题相关的部分。在这种情况下,我认为只有一些app.use行和第二个代码片段是真正必要的。 - Squirrel
3个回答

11

如果您想发送原始数据并使用body parser接收,只需按照以下方式配置:

app.use(bodyParser.raw({ inflate: true, limit: '100kb', type: 'text/xml' }));

那种行为不会破坏正文内容。


6
重要的是添加"type"参数。如果省略"type",默认行为是检查类型为"application/octet-stream",如这里所示(对于大多数库的用户而言可能是出乎意料的)。要匹配任何内容类型,请使用"type:“*/*”"。 - Odysseas
@Odysseas说“检查”是误导性的。正确的词是“默认为”。感谢提供链接。var type = opts.type || "application/octet-stream" - Gilbert

8
为了解析所有内容类型,我使用以下方法:
app.use(
  express.raw({
    inflate: true,
    limit: '50mb',
    type: () => true, // this matches all content types
  })
);

在单个路由中获取原始请求体:

app.put('/upload', express.raw({ inflate: true, limit: '50mb', type: () => true }), async (req, res) => {
  res.json({ bodySize: req.body.length });
});

在这种情况下,请注意之前使用的Body解析器(例如json)将首先被执行- 因此请检查req.body确实为Buffer,否则恶意调用者可能会发送类似于{"length":9999999}且带有Content-Type: application/json的内容。


4

解析后的内容应该设置在req.body上。

请注意,中间件按照使用app.use的顺序应用,我理解如果多次应用bodyParser将尝试按照顺序解析请求体,最终留下最后一个middleware操作req.body的结果。 因为bodyParser.json()和bodyParser.raw()都接受任何输入,所以您最终会尝试将所有内容从缓冲区解析为JSON。


有没有什么方法可以将 bodyParser.raw() 中间件限制为特定的 Content-Type - Believe2014
2
很好的问题,显然是有的!从文档[1](https://www.npmjs.com/package/body-parser#bodyparserrawoptions)中可以看到:raw函数接受一个选项options对象,该对象可能包含以下任何键:type选项用于确定中间件将解析哪种媒体类型。此选项可以是函数或字符串...它甚至接受mime类型的通配符,因此您应该可以根据需要进行细分。 - Squirrel
让我进一步扩展,你能够将一些路由端点解析为原始格式,而将其余部分保留为JSON吗? - Peter Poliwoda

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