UNPKG

express-xml-bodyparser

Version:
149 lines (116 loc) 2.84 kB
'use strict'; /** * Module dependencies. */ var xml2js = require('xml2js'); var http = require('http'); var regexp = /^(text\/xml|application\/([\w!#\$%&\*`\-\.\^~]+\+)?xml)$/i; /** * Module exports. */ module.exports = xmlparser; module.exports.regexp = regexp; /** * Expose configuration for xml-bodyparser middleware * * @api public * @param {Object} [options] Parser options * @return {Function} */ function xmlparser(options) { var parserOptions = Object.assign({ async: false, explicitArray: true, normalize: true, normalizeTags: true, trim: true }, options || {}); return xmlbodyparser; /** * Provide connect/express-style middleware * * @param {IncomingMessage} req * @param {ServerResponse} res * @param {Function} next * @return {*} */ function xmlbodyparser(req, res, next) { var data = ''; var parser = new xml2js.Parser(parserOptions); /** * @param {Error} err * @param {Object} [xml] */ var responseHandler = function (err, xml) { if (err) { err.status = 400; return next(err); } req.body = xml || req.body; req.rawBody = data; next(); }; if (req._body) { return next(); } req.body = req.body || {}; if (!hasBody(req) || !module.exports.regexp.test(mime(req))) { return next(); } req._body = true; // explicitly cast incoming to string req.setEncoding('utf-8'); req.on('data', function (chunk) { data += chunk; }); // in case `parseString` callback never was called, ensure response is sent parser.saxParser.onend = function() { if (req.complete && req.rawBody === undefined) { return responseHandler(null); } }; req.on('end', function () { // invalid xml, length required if (data.trim().length === 0) { return next(error(411)); } parser.parseString(data, responseHandler); }); } } /** * Test whether request has body * * @see connect.utils * @param {IncomingMessage} req * @return {boolean} */ function hasBody(req) { var encoding = 'transfer-encoding' in req.headers; var length = 'content-length' in req.headers && req.headers['content-length'] !== '0'; return encoding || length; } /** * Get request mime-type without character encoding * * @see connect.utils * @param {IncomingMessage} req * @return {string} */ function mime(req) { var str = req.headers['content-type'] || ''; return str.split(';')[0]; } /** * Factory for new Error with statuscode * * @see connect.utils * @param {number} code * @param {string} [msg] * @return {Error} */ function error(code, msg) { var err = new Error(msg || http.STATUS_CODES[code]); err.status = code; return err; }