当 content-type 有多个值时,body-parser 变为空 body

body-parser get empty body when content-type have multiple values

我从 express 3 升级到 4,body 解析中间件已经改变,所以我使用 body-parser 并且在大多数情况下它看起来不错:

var bodyParser = require('body-parser');

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

但我有一个第三方服务,它会调用我的特定 url 之一来通知消息,它​​在 express 3 中工作正常,但在 express 4 中失败,因为 req.body 是空的

我调试请求header,发现Content-Typeapplication/x-www-form-urlencoded; text/html; charset=UTF-8而不是application/x-www-form-urlencoded

所以我在curl中测试,当我删除text/html; charset=UTF-8时,req.body可以准确显示我的post body。

那我该怎么办呢?这是第 3 方服务,他们没有理由更改代码,有节点方式吗? tks

根据文档 http://greenbytes.de/tech/webdav/rfc2616.html#rfc.section.14.17Content-Type 的请求 header 格式错误。 所以问题是请求 header 有两个 media-type,body-parser 中间件将其处理 text/html.

最后我专门为这个请求写了一个中间件,检测是否包含单词application/x-www-form-urlencoded,然后我qs.parse(buffString)临时解决

app.use(function(req, res, next){
  if(/^\/pay\/ali\/notify/.test(req.originalUrl)){
    req.body = req.body || {};
    if ('POST' != req.method) return next();
    var contenttype = req.headers['content-type'];
    if(!/application\/x-www-form-urlencoded/.test(contenttype)) return next();
    req._body = true;
    var buf = '';
    req.setEncoding('utf8');
    req.on('data', function(chunk){ buf += chunk });
    req.on('end', function(){
      req.body = qs.parse(buf);
      next();
    });
  }else{
    next();
  }
});

或者你可以像支付宝一样强制urlencoded app.post('/alipay', bodyParser.urlencoded({ extended: true, type: function() {return true;} }))