Spaces:
Sleeping
Sleeping
| /*! | |
| * http-errors | |
| * Copyright(c) 2014 Jonathan Ong | |
| * Copyright(c) 2016 Douglas Christopher Wilson | |
| * MIT Licensed | |
| */ | |
| /** | |
| * Module dependencies. | |
| * @private | |
| */ | |
| var deprecate = require('depd')('http-errors') | |
| var setPrototypeOf = require('setprototypeof') | |
| var statuses = require('statuses') | |
| var inherits = require('inherits') | |
| var toIdentifier = require('toidentifier') | |
| /** | |
| * Module exports. | |
| * @public | |
| */ | |
| module.exports = createError | |
| module.exports.HttpError = createHttpErrorConstructor() | |
| module.exports.isHttpError = createIsHttpErrorFunction(module.exports.HttpError) | |
| // Populate exports for all constructors | |
| populateConstructorExports(module.exports, statuses.codes, module.exports.HttpError) | |
| /** | |
| * Get the code class of a status code. | |
| * @private | |
| */ | |
| function codeClass (status) { | |
| return Number(String(status).charAt(0) + '00') | |
| } | |
| /** | |
| * Create a new HTTP Error. | |
| * | |
| * @returns {Error} | |
| * @public | |
| */ | |
| function createError () { | |
| // so much arity going on ~_~ | |
| var err | |
| var msg | |
| var status = 500 | |
| var props = {} | |
| for (var i = 0; i < arguments.length; i++) { | |
| var arg = arguments[i] | |
| var type = typeof arg | |
| if (type === 'object' && arg instanceof Error) { | |
| err = arg | |
| status = err.status || err.statusCode || status | |
| } else if (type === 'number' && i === 0) { | |
| status = arg | |
| } else if (type === 'string') { | |
| msg = arg | |
| } else if (type === 'object') { | |
| props = arg | |
| } else { | |
| throw new TypeError('argument #' + (i + 1) + ' unsupported type ' + type) | |
| } | |
| } | |
| if (typeof status === 'number' && (status < 400 || status >= 600)) { | |
| deprecate('non-error status code; use only 4xx or 5xx status codes') | |
| } | |
| if (typeof status !== 'number' || | |
| (!statuses.message[status] && (status < 400 || status >= 600))) { | |
| status = 500 | |
| } | |
| // constructor | |
| var HttpError = createError[status] || createError[codeClass(status)] | |
| if (!err) { | |
| // create error | |
| err = HttpError | |
| ? new HttpError(msg) | |
| : new Error(msg || statuses.message[status]) | |
| Error.captureStackTrace(err, createError) | |
| } | |
| if (!HttpError || !(err instanceof HttpError) || err.status !== status) { | |
| // add properties to generic error | |
| err.expose = status < 500 | |
| err.status = err.statusCode = status | |
| } | |
| for (var key in props) { | |
| if (key !== 'status' && key !== 'statusCode') { | |
| err[key] = props[key] | |
| } | |
| } | |
| return err | |
| } | |
| /** | |
| * Create HTTP error abstract base class. | |
| * @private | |
| */ | |
| function createHttpErrorConstructor () { | |
| function HttpError () { | |
| throw new TypeError('cannot construct abstract class') | |
| } | |
| inherits(HttpError, Error) | |
| return HttpError | |
| } | |
| /** | |
| * Create a constructor for a client error. | |
| * @private | |
| */ | |
| function createClientErrorConstructor (HttpError, name, code) { | |
| var className = toClassName(name) | |
| function ClientError (message) { | |
| // create the error object | |
| var msg = message != null ? message : statuses.message[code] | |
| var err = new Error(msg) | |
| // capture a stack trace to the construction point | |
| Error.captureStackTrace(err, ClientError) | |
| // adjust the [[Prototype]] | |
| setPrototypeOf(err, ClientError.prototype) | |
| // redefine the error message | |
| Object.defineProperty(err, 'message', { | |
| enumerable: true, | |
| configurable: true, | |
| value: msg, | |
| writable: true | |
| }) | |
| // redefine the error name | |
| Object.defineProperty(err, 'name', { | |
| enumerable: false, | |
| configurable: true, | |
| value: className, | |
| writable: true | |
| }) | |
| return err | |
| } | |
| inherits(ClientError, HttpError) | |
| nameFunc(ClientError, className) | |
| ClientError.prototype.status = code | |
| ClientError.prototype.statusCode = code | |
| ClientError.prototype.expose = true | |
| return ClientError | |
| } | |
| /** | |
| * Create function to test is a value is a HttpError. | |
| * @private | |
| */ | |
| function createIsHttpErrorFunction (HttpError) { | |
| return function isHttpError (val) { | |
| if (!val || typeof val !== 'object') { | |
| return false | |
| } | |
| if (val instanceof HttpError) { | |
| return true | |
| } | |
| return val instanceof Error && | |
| typeof val.expose === 'boolean' && | |
| typeof val.statusCode === 'number' && val.status === val.statusCode | |
| } | |
| } | |
| /** | |
| * Create a constructor for a server error. | |
| * @private | |
| */ | |
| function createServerErrorConstructor (HttpError, name, code) { | |
| var className = toClassName(name) | |
| function ServerError (message) { | |
| // create the error object | |
| var msg = message != null ? message : statuses.message[code] | |
| var err = new Error(msg) | |
| // capture a stack trace to the construction point | |
| Error.captureStackTrace(err, ServerError) | |
| // adjust the [[Prototype]] | |
| setPrototypeOf(err, ServerError.prototype) | |
| // redefine the error message | |
| Object.defineProperty(err, 'message', { | |
| enumerable: true, | |
| configurable: true, | |
| value: msg, | |
| writable: true | |
| }) | |
| // redefine the error name | |
| Object.defineProperty(err, 'name', { | |
| enumerable: false, | |
| configurable: true, | |
| value: className, | |
| writable: true | |
| }) | |
| return err | |
| } | |
| inherits(ServerError, HttpError) | |
| nameFunc(ServerError, className) | |
| ServerError.prototype.status = code | |
| ServerError.prototype.statusCode = code | |
| ServerError.prototype.expose = false | |
| return ServerError | |
| } | |
| /** | |
| * Set the name of a function, if possible. | |
| * @private | |
| */ | |
| function nameFunc (func, name) { | |
| var desc = Object.getOwnPropertyDescriptor(func, 'name') | |
| if (desc && desc.configurable) { | |
| desc.value = name | |
| Object.defineProperty(func, 'name', desc) | |
| } | |
| } | |
| /** | |
| * Populate the exports object with constructors for every error class. | |
| * @private | |
| */ | |
| function populateConstructorExports (exports, codes, HttpError) { | |
| codes.forEach(function forEachCode (code) { | |
| var CodeError | |
| var name = toIdentifier(statuses.message[code]) | |
| switch (codeClass(code)) { | |
| case 400: | |
| CodeError = createClientErrorConstructor(HttpError, name, code) | |
| break | |
| case 500: | |
| CodeError = createServerErrorConstructor(HttpError, name, code) | |
| break | |
| } | |
| if (CodeError) { | |
| // export the constructor | |
| exports[code] = CodeError | |
| exports[name] = CodeError | |
| } | |
| }) | |
| } | |
| /** | |
| * Get a class name from a name identifier. | |
| * @private | |
| */ | |
| function toClassName (name) { | |
| return name.substr(-5) !== 'Error' | |
| ? name + 'Error' | |
| : name | |
| } | |