You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							266 lines
						
					
					
						
							5.7 KiB
						
					
					
				
			
		
		
	
	
							266 lines
						
					
					
						
							5.7 KiB
						
					
					
				/*! | 
						|
 * 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() | 
						|
 | 
						|
// 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] | 
						|
    if (arg instanceof Error) { | 
						|
      err = arg | 
						|
      status = err.status || err.statusCode || status | 
						|
      continue | 
						|
    } | 
						|
    switch (typeof arg) { | 
						|
      case 'string': | 
						|
        msg = arg | 
						|
        break | 
						|
      case 'number': | 
						|
        status = arg | 
						|
        if (i !== 0) { | 
						|
          deprecate('non-first-argument status code; replace with createError(' + arg + ', ...)') | 
						|
        } | 
						|
        break | 
						|
      case 'object': | 
						|
        props = arg | 
						|
        break | 
						|
    } | 
						|
  } | 
						|
 | 
						|
  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[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[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 = name.match(/Error$/) ? name : name + 'Error' | 
						|
 | 
						|
  function ClientError (message) { | 
						|
    // create the error object | 
						|
    var msg = message != null ? message : statuses[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 a constructor for a server error. | 
						|
 * @private | 
						|
 */ | 
						|
 | 
						|
function createServerErrorConstructor (HttpError, name, code) { | 
						|
  var className = name.match(/Error$/) ? name : name + 'Error' | 
						|
 | 
						|
  function ServerError (message) { | 
						|
    // create the error object | 
						|
    var msg = message != null ? message : statuses[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[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 | 
						|
    } | 
						|
  }) | 
						|
 | 
						|
  // backwards-compatibility | 
						|
  exports["I'mateapot"] = deprecate.function(exports.ImATeapot, | 
						|
    '"I\'mateapot"; use "ImATeapot" instead') | 
						|
}
 | 
						|
 |