restify
Version:
REST framework
149 lines (116 loc) • 4.42 kB
JavaScript
;
var http = require('http');
var _ = require('lodash');
var assert = require('assert-plus');
//------------------------------------------------------------------------------
// constructor arg parsers
//------------------------------------------------------------------------------
/**
* helper function for parsing all of the Error constructor variadic sigs.
* First two are special to Restify, using a options obj.
* 1) new HttpError(anotherErr, {...});
* 2) new HttpError({...});
* Last two are straight pass through to WError
* 3) new HttpError('my special error message');
* 4) new HttpError(anotherErr, '', '');
* @public
* @function parseVariadicArgs
* @param {Object} ctorArgs the passed in arguments object to error
* constructor
* @param {Boolean} werrorSuper if the super being invoked is going to
* WError
* @returns {Object}
*/
function parseVariadicArgs(ctorArgs, werrorSuper) {
function parse() {
// to array the inner arguments
var args = _.toArray(arguments);
var options = null;
// 1)
if (arguments[0] instanceof Error) {
// 1)
if (_.isPlainObject(arguments[1])) {
options = arguments[1] || {};
// if we're calling WError super, don't pass in the special
// restify options object.
if (werrorSuper === true) {
args = [arguments[0]];
}
}
// 4)
// otherwise, pass through to WError
}
// 2)
else if (_.isPlainObject(arguments[0])) {
options = arguments[0] || {};
// if we're calling WError super, don't pass in the special restify
// options object. pass all subsequent args, which could include
// extsprintf style strings.
if (werrorSuper === true) {
// drop first arg
args = _.drop(args);
}
// if we have an options object, assert them.
assert.optionalObject(options, 'options');
assert.optionalString(options.message, 'options.message');
assert.optionalNumber(options.statusCode, 'options.statusCode');
}
// 3
// otherwise, pass through to WError
return {
args: args,
options: options
};
}
// call constructor args.
return parse.apply(null, ctorArgs);
}
//------------------------------------------------------------------------------
// helpers
//------------------------------------------------------------------------------
/**
* create an error name from a status code. looks up the description via
* http.STATUS_CODES, then calls createErrNameFromDesc().
* @private
* @function errNameFromCode
* @param {Number} code an http status code
* @returns {String}
*/
function errNameFromCode(code) {
assert.number(code, 'code');
// attempt to retrieve status code description, if not available,
// fallback on 500.
var errorDesc = http.STATUS_CODES[code] || http.STATUS_CODES[500];
return errNameFromDesc(errorDesc);
}
/**
* used to programatically create http error code names, using the underlying
* status codes names exposed via the http module.
* @private
* @function errNameFromDesc
* @param {String} desc a description of the error, e.g., 'Not Found'
* @returns {String}
*/
function errNameFromDesc(desc) {
assert.string(desc, 'desc');
// takes an error description, split on spaces, camel case it correctly,
// then append 'Error' at the end of it.
// e.g., the passed in description is 'Internal Server Error'
// the output is 'InternalServerError'
var pieces = desc.split(/\s+/);
var name = _.reduce(pieces, function(acc, piece) {
// lowercase all, then capitalize it.
var normalizedPiece = _.capitalize(piece.toLowerCase());
return acc + normalizedPiece;
}, '');
// strip all non word characters
name = name.replace(/\W+/g, '');
// append 'Error' at the end of it only if it doesn't already end with it.
if (!_.endsWith(name, 'Error')) {
name += 'Error';
}
return name;
}
module.exports.errNameFromCode = errNameFromCode;
module.exports.errNameFromDesc = errNameFromDesc;
module.exports.parseVariadicArgs = parseVariadicArgs;