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

时间:2013-09-10 03:24:13

标签: node.js express request

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

app.use(express.bodyParser());

我如何获得原始请求正文

7 个答案:

答案 0 :(得分:65)

编辑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

答案 1 :(得分:36)

我使用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的新手(从昨天开始,字面意思!)所以我想听听有关此解决方案的评论。

答案 2 :(得分:22)

请小心处理其他答案,因为如果您还希望同时支持json,urlencoded等,它们将无法正常使用bodyParser。要使其与bodyParser一起使用,您应该将处理程序设置为仅在你关心的Content-Type标题,就像bodyParser本身一样。

要将Content-Type: "text/plain"的{​​{1}}请求的原始内容转换为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();
  });
});

答案 3 :(得分:16)

这个解决方案对我有用:

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) { });解决方案时,它无法处理分块请求正文。

答案 4 :(得分: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());

答案 5 :(得分:0)

使用body-parser解析正文及其内容:

app.use(bodyParser.text());

app.use(bodyParser.urlencoded());

app.use(bodyParser.raw());

app.use(bodyParser.json());

即。如果应该获取原始文本文件,请运行.text()

那是body解析器当前支持的

答案 6 :(得分:0)

// 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;