Node | 如何用express解析xml格式请求

954 阅读2分钟

前言

有一次在我的工作中,我发现第三方发的xml格式post请求,我这边req.body接收一直为空对象,查阅资料后发现原来是express不支持xml格式的请求,这里引用别的大佬博客的话:

express 是基于 connect 开发的,使用 bodyParser 对请求的包体进行解析,默认支持:application/jsonapplication/x-www-form-urlencoded, 以及 multipart/form-data。 也就是说不支持对 XML 形式的包体进行解析。

方案分析

在这个过程中我找到两种解决方案:

  1. 直接使用第三方插件:例如express-xml-bodyparser(使用方法请到参考文章对应部分查阅)
  2. 构造一个中间件,在请求到达业务处理逻辑之前,将请求体的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();
            }
        });
    });
};


参考文章:

  1. Node.js 接收xml格式请求
  2. 如何让 Node-express 支持 XML 形式的 POST 请求?