| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 | /*! * 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 = createErrormodule.exports.HttpError = createHttpErrorConstructor()module.exports.isHttpError = createIsHttpErrorFunction(module.exports.HttpError)// Populate exports for all constructorspopulateConstructorExports(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}
 |