UNPKG

restify

Version:
153 lines (129 loc) 4.49 kB
'use strict'; // core modules var util = require('util'); // external modules var WError = require('verror').WError; // internal files var helpers = require('./../helpers'); /** * Base HttpError class. inherits from WError. * Variadic signature, first two are special to Restify, using a options obj. * 1) new HttpError(anotherErr, {...}); * 2) new HttpError({...}); * Last one is a straight pass through to WError * 3) new HttpError('my special error message'); * @public * @class */ function HttpError() { var self = this; // normalize the signatures var parsed = helpers.parseVariadicArgs(arguments, true); var args = parsed.args; var options = parsed.options || {}; // inherit from WError, call super first before doing anything else! WError // will handle calling captureStackTrace, using arguments.callee to // eliminate unnecessary stack frames. WError.apply(self, args); /** * the error message. * since constructor can be invoked with both options.message, as well as * printf style messages, prefer the printf style messages that are already * set by WError constructor. Since we've already invoked WError constructor * at this point, only use options.message value if message is not yet * defined. in short, prefer printf messages over options.message when both * are passed in. support default message if set on the prototype for custom * constructors. * @property * @type {String} */ if (!self.message) { self.message = (options.message || self.message) || Object.getPrototypeOf(self).message || ''; } /** * the http status code of the error. * because inherited classes have status code set on the prototype, * only assign a status code if truthy. * @property * @type {Number} */ if (options.statusCode) { self.statusCode = options.statusCode; } /** * property used to describe the error. emulates some of the core module * errors that have codes on them to describe their nature, * i.e., fs.readFile can return an ENOENT error where err.code is 'ENOENT' * @property * @type {String} */ if (options.code) { self.code = options.code; } /** * an object used to render the error when passed * to res.send() * @property * @type {Object} */ self.body = { // err.code/err.restCode is used by legacy restify paths, probably // originally created to emulate the code property that is created by // some native core module errors (i.e., a failed fs.readFile will // return a ENOENT error with a err.code of ENOENT). // // for Http/RestErrors, the code will be the error name but with // 'error' truncated from the string. i.e., if the error name is // InternalServerError, the code is InternalServer. code: options.code || self.code, message: self.message || '' }; /** * an object of random properties that may be added to the object upon * instantion. useful for capturing context around a specific error. * @property * @type {Object} */ self.context = options.context || null; } util.inherits(HttpError, WError); /** * assign non-standard display name property on the CONSTRUCTOR (not prototype), * which is supported by all VMs. useful for stack trace output. * @type {String} */ HttpError.displayName = 'HttpError'; /** * the name of the error, used in the stack trace output * @type {String} */ HttpError.prototype.name = 'HttpError'; /** * the default error code * @type {String} */ HttpError.prototype.code = 'Error'; /** * implement a basic toString/JSON.stringify. they should be identical. * @public * @method toJSON * @returns {String} */ HttpError.prototype.toJSON = function toJSON() { var self = this; var message = ''; // if we have a cause, get the full VError toString() without the current // error name. verbose check, self.cause can exist but returns undefined if (self.cause && typeof self.cause === 'function' && self.cause()) { var fullString = self.toString(); message = fullString.substr(fullString.indexOf(' ') + 1); } else { message = self.body.message; } return { code: self.body.code, message: message }; }; module.exports = HttpError;