Skip to content

Commit

Permalink
#970 xml error formatter simplified & more unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
brianhyder committed Nov 23, 2016
1 parent df30e4d commit 30c3aa3
Show file tree
Hide file tree
Showing 6 changed files with 254 additions and 104 deletions.
61 changes: 7 additions & 54 deletions include/error/formatters/error_formatters.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@

//dependencies
var path = require('path');
var HtmlEncoder = require('htmlencode');
var HttpStatusCodes = require('http-status-codes');
var XmlErrorFormatter = require('./xml_error_formatter');

module.exports = function(pb) {

Expand All @@ -42,16 +43,6 @@ module.exports = function(pb) {
*/
var DEFAULT_MIME = 'text/html';

/**
* Error code when a validation failure occurs
* @private
* @static
* @readonly
* @property BAD_REQUEST
* @type {Integer}
*/
var BAD_REQUEST = 400;

/**
* Converts an error to a plain object that can be serialized
* @private
Expand All @@ -68,7 +59,7 @@ module.exports = function(pb) {
if (pb.config.logging.showErrors) {
content.stack = params.error.stack;
}
if (params.error.code === BAD_REQUEST) {
if (params.error.code === HttpStatusCodes.BAD_REQUEST) {
delete content.stack;
content.validationErrors = params.error.validationErrors;
}
Expand Down Expand Up @@ -125,7 +116,7 @@ module.exports = function(pb) {
}

//let the default error controller handle it.
var code = params.error.code || 500;
var code = params.error.code || HttpStatusCodes.INTERNAL_SERVER_ERROR;
var ErrorController = null;
var paths = [
path.join(pb.config.docRoot, 'plugins', params.activeTheme, 'controllers/error', code + '.js'),
Expand Down Expand Up @@ -173,46 +164,8 @@ module.exports = function(pb) {
*/
ErrorFormatters.xml = function(params, cb) {

var xmlObj = function(key, obj) {
var xml = '<' + HtmlEncoder.htmlEncode(key) + '>';
util.forEach(obj, function(val, key) {

if (util.isArray(val)) {
xml += xmlArray(key, val);
}
else if (util.isObject(val)) {
xml += xmlObj(key, val);
}
else {
xml += '<'+HtmlEncoder.htmlEncode(key)+'>' + HtmlEncoder.htmlEncode(val + '') + '</'+HtmlEncoder.htmlEncode(key)+'>';
}
});
xml += '</'+HtmlEncoder.htmlEncode(key)+'>';
return xml;
};
var xmlArray = function(key, obj) {
var xml = '';
util.forEach(obj, function(val, i) {

if (util.isArray(val)) {
xml += xmlArray(key+'_'+i, val);
}
else if (util.isObject(val)) {
xml += xmlObj(key, val);
}
else {
xml += '<'+HtmlEncoder.htmlEncode(key)+'>' + HtmlEncoder.htmlEncode(val + '') + '</'+HtmlEncoder.htmlEncode(key)+'>';
}
});
return xml;
};
var xmlPrimitive = function(key, val) {
return '<'+HtmlEncoder.htmlEncode(key)+'>' + HtmlEncoder.htmlEncode(val + '') + '</'+HtmlEncoder.htmlEncode(key)+'>';
};
cb(
null,
xmlObj('error', convertToObject(params))
);
var objToSerialize = convertToObject(params);
cb(null, XmlErrorFormatter.serialize(objToSerialize));
};

/**
Expand Down Expand Up @@ -324,7 +277,7 @@ module.exports = function(pb) {
'text/json': ErrorFormatters.json,
'text/html': ErrorFormatters.html,
'application/xml': ErrorFormatters.xml,
'text/xml': ErrorFormatters.xml,
'text/xml': ErrorFormatters.xml
});

/**
Expand Down
118 changes: 118 additions & 0 deletions include/error/formatters/xml_error_formatter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
Copyright (C) 2016 PencilBlue, LLC
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
'use strict';

//dependencies
var HtmlEncoder = require('htmlencode');

/**
* Responsible for formatting an error as XML
* @class XmlErrorFormatter
*/
class XmlErrorFormatter {

/**
* Serializes the object version of the error to be formatted
* @method serialize
* @param {object} params
* @returns {string}
*/
static serialize(params) {
return XmlErrorFormatter.serializeXmlObject('error', params);
}

/**
* @static
* @method serializeXmlPrimitive
* @param {string} key
* @param {*} val
* @returns {string}
*/
static serializeXmlPrimitive (key, val) {
return XmlErrorFormatter.startElement(key) + HtmlEncoder.htmlEncode(val + '') + XmlErrorFormatter.endElement(key);
}

/**
* @static
* @method serializeXmlArray
* @param {string} key
* @param {Array} obj
* @returns {string}
*/
static serializeXmlArray (key, obj) {
var xml = '';
obj.forEach(function(prop, i) {
var val = obj[prop];
if (Array.isArray(val)) {
xml += XmlErrorFormatter.serializeXmlArray(key + '_' + i, val);
}
else if (typeof val === 'object') {
xml += XmlErrorFormatter.serializeXmlObject(key, val);
}
else {
xml += XmlErrorFormatter.serializeXmlPrimitive(key, val);
}
});
return xml;
}

/**
* @static
* @method serializeXmlObject
* @param {string} key
* @param {object} obj
* @returns {string}
*/
static serializeXmlObject (key, obj) {
var xml = XmlErrorFormatter.startElement(key);
Object.keys(obj).forEach(function(val) {
if (Array.isArray(val)) {
xml += XmlErrorFormatter.serializeXmlArray(key, val);
}
else if (typeof val === 'object') {
xml += XmlErrorFormatter.serializeXmlObject(key, val);
}
else {
xml += XmlErrorFormatter.serializeXmlPrimitive(key, val);
}
});
xml += XmlErrorFormatter.endElement(key);
return xml;
}

/**
* @static
* @method startElement
* @param {string} key
* @returns {string}
*/
static startElement (key) {
return '<' + HtmlEncoder.htmlEncode(key) + '>';
}

/**
* @static
* @method endElement
* @param {string} key
* @returns {string}
*/
static endElement (key) {
return '</' + HtmlEncoder.htmlEncode(key) + '>';
}
}

module.exports = XmlErrorFormatter;
16 changes: 16 additions & 0 deletions include/http/middleware/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/*
Copyright (C) 2016 PencilBlue, LLC
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
'use strict';

//dependencies
Expand Down
Loading

0 comments on commit 30c3aa3

Please sign in to comment.