前言
有一次在我的工作中,我发现第三方发的xml格式post请求,我这边req.body接收一直为空对象,查阅资料后发现原来是express不支持xml格式的请求,这里引用别的大佬博客的话:
express 是基于 connect 开发的,使用 bodyParser 对请求的包体进行解析,默认支持:
application/json,application/x-www-form-urlencoded, 以及multipart/form-data。 也就是说不支持对 XML 形式的包体进行解析。
方案分析
在这个过程中我找到两种解决方案:
- 直接使用第三方插件:例如express-xml-bodyparser(使用方法请到参考文章对应部分查阅)
- 构造一个中间件,在请求到达业务处理逻辑之前,将请求体的xml数据接收,最好转换成json格式,方便后续处理
由于工作项目需要引入新的第三方插件存在潜在风险,我选择了后者
实现过程
对于xml数据的接收,首先我们需要判断出请求是不是xml格式,我们可以借用req.is方法:
express中的req.is()方法:可以检查请求的content-type类型,该函数如果正确返回字符串,错误返回false(布尔值)
比如:我想检测请求的
content-type是否是text/xml, 可以使用req.is('text/xml'),如果请求是xml格式的话返回'text/xml',不是则返回false
由于req.body为{},我们得想个办法拿到请求体的数据,这个时候得用到req.on()方法
var buf = '';
req.setEncoding('utf8'); // 设置编码格式
req.on('data', chunk => buf += chunk ); // 将每次收到的数据段进行拼接(数据的接收不是一个连续的过程)
req.on('end', () => console.log('数据:', buf)); // 等数据接收完毕就会触发end,然后执行回调函数,打印buf
对于xml的解析,目前比较好用的一个库是xml2js,也是我项目内置的,所以就直接使用它了,xml2js是一个用于将xml进行各种处理的库,其中也有数据类型的转换,功能强大,使用起来也很简单,这里就不展开说它的使用了,百度一下就好
下面是完整实现:
app.use(express.logger('dev')); /* 'default', 'short', 'tiny', 'dev' */
app.use(express.bodyParser())
app.use(xmlBodyParser)
// express不支持xml请求,此方法用于兼容xml请求,将请求体的xml转成json
function xmlBodyParser(req, res, next) {
if (req._body) return next();
req.body = req.body || {};
// ignore GET
if ('GET' == req.method || 'HEAD' == req.method) return next();
// check Content-Type
if (!req.is('text/xml')) return next();
// flag as parsed
req._body = true;
// parse
var buf = '';
req.setEncoding('utf8');
req.on('data', function(chunk){ buf += chunk });
req.on('end', function(){
var parseString = xml2js.parseString;
parseString(buf, function(err, json) {
if (err) {
err.status = 400;
next(err);
} else {
req.body = json;
next();
}
});
});
};
参考文章: