Node.js - 使用Express获取原始请求正文

hai*_*_wu 61 request node.js express

当我使用Express时,我的代码是:

app.use(express.bodyParser());
Run Code Online (Sandbox Code Playgroud)

我如何获得原始请求正文

hex*_*ide 71

编辑2:正文解析器模块的版本1.15.2引入了原始模式,它将主体作为缓冲区返回.默认情况下,它还会自动处理deflate和gzip解压缩.用法示例:

var bodyParser = require('body-parser');
app.use(bodyParser.raw(options));

app.get(path, function(req, res) {
  // req.body is a Buffer object
});
Run Code Online (Sandbox Code Playgroud)

默认情况下,该options对象具有以下默认选项:

var options = {
  inflate: true,
  limit: '100kb',
  type: 'application/octet-stream'
};
Run Code Online (Sandbox Code Playgroud)

如果您希望原始解析器解析除其他MIME类型之外的其他MIME类型application/octet-stream,则需要在此处进行更改.它还支持通配符匹配,如*/**/application.


注意:以下答案适用于Express 4之前的版本,其中中间件仍与框架捆绑在一起.现代的等价物是body-parser模块,必须单独安装.

rawBodyExpress中的属性曾经可用,但从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());
Run Code Online (Sandbox Code Playgroud)

该中间件将从实际数据流中读取,并将其存储在rawBody请求的属性中.然后,您可以像这样访问原始主体:

app.post('/', function(req, res) {
  // do something with req.rawBody
  // use req.body for the parsed body
});
Run Code Online (Sandbox Code Playgroud)

编辑:似乎这个方法和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];
  ...
});
Run Code Online (Sandbox Code Playgroud)

你会在这个位置找到该文件:

/node_modules/express/node_modules/connect/lib/middleware/json.js.


Tia*_* A. 40

我使用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);

    }
}));
Run Code Online (Sandbox Code Playgroud)

我是Node.js和express.js的新手(昨天从字面上开始!)所以我想听听有关此解决方案的评论.

  • 我非常喜欢这个解决方案.我刚刚包含了`req.rawBody = buf.toString();`并将其余部分从`verify`函数中删除,因为这就是我所需要的,并且它工作得很漂亮.无需更改bodyParser源代码! (3认同)
  • 非常好.我可以建议`req.rawBody = buf.toString(encoding);` (3认同)
  • 这将只捕获`application/json`请求 (2认同)

nor*_*ron 24

请小心处理其他答案,因为如果你想要支持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();
  });
});
Run Code Online (Sandbox Code Playgroud)

  • +1.我尝试了上面的解决方案之一,然后我的所有GET和json帖子都失败了.上述解决方案在技术上对于问题是正确的,但如果您使用多种形式的数据处理更多样化的请求,则需要这样做. (3认同)

Pav*_*eev 24

这个解决方案对我有用:

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: '*/*' }));
Run Code Online (Sandbox Code Playgroud)

当我使用解决方案时,req.on('data', function(chunk) { });它不在chunked请求体上工作.

  • 我试图验证 Shopify 应用网络钩子的 hmac,这对我有用。我大致遵循了这个例子:https://gist.github.com/andjosh/5c4f0244914adfd312e4。 (2认同)

Nis*_*hah 24

2022年

获取每个 API 的最佳方法raw body是将 buffer 转换为字符串。

在此输入图像描述

app.use(
  express.json({
    limit: '5mb',
    verify: (req, res, buf) => {
      req.rawBody = buf.toString();
    },
  })
);
Run Code Online (Sandbox Code Playgroud)

  • 优雅且适合我。不需要中间件,并且不会干扰其他 req 对象。 (3认同)
  • 同意,这对于修复 stripe webhook 集成非常有用! (2认同)

ofe*_*rei 13

这是六氰化物上述答案的变体.此中间件还处理"数据"事件,但不会在调用"下一个"之前等待数据被消耗.这样,这个中间件和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());
Run Code Online (Sandbox Code Playgroud)

  • 这似乎不适用于早期被切断的长身体. (2认同)