| /*! | 
|  * http-errors | 
|  * Copyright(c) 2014 Jonathan Ong | 
|  * Copyright(c) 2016 Douglas Christopher Wilson | 
|  * MIT Licensed | 
|  */ | 
|   | 
| 'use strict' | 
|   | 
| /** | 
|  * 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 | 
| } |