当content-type有多个值

时间:2015-07-09 04:54:23

标签: express body-parser

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

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

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

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

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

所以我在curl中进行了测试,当我移除text/html; charset=UTF-8时,req.body可以完全显示我的帖子正文。

那我该怎么办?这是第三方服务,他们没有理由改变他们的代码,是否有节点方式? TKS

2 个答案:

答案 0 :(得分:2)

根据文档http://greenbytes.de/tech/webdav/rfc2616.html#rfc.section.14.17Content-Type的请求标头格式不正确。 所以问题是请求标头有两个媒体类型,正文解析器中间件将它视为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();
  }
});

答案 1 :(得分:1)

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