3 * Copyright(c) 2014 Jonathan Ong
4 * Copyright(c) 2016 Douglas Christopher Wilson
11 * Module dependencies.
15 var setPrototypeOf = require('setprototypeof')
16 var statuses = require('statuses')
17 var inherits = require('inherits')
24 module.exports = createError
25 module.exports.HttpError = createHttpErrorConstructor()
27 // Populate exports for all constructors
28 populateConstructorExports(module.exports, statuses.codes, module.exports.HttpError)
31 * Create a new HTTP Error.
37 function createError () {
38 // so much arity going on ~_~
43 for (var i = 0; i < arguments.length; i++) {
44 var arg = arguments[i]
45 if (arg instanceof Error) {
47 status = err.status || err.statusCode || status
63 if (typeof status !== 'number' || !statuses[status]) {
68 var HttpError = createError[status]
74 : new Error(msg || statuses[status])
75 Error.captureStackTrace(err, createError)
78 if (!HttpError || !(err instanceof HttpError)) {
79 // add properties to generic error
80 err.expose = status < 500
81 err.status = err.statusCode = status
84 for (var key in props) {
85 if (key !== 'status' && key !== 'statusCode') {
94 * Create HTTP error abstract base class.
98 function createHttpErrorConstructor () {
99 function HttpError () {
100 throw new TypeError('cannot construct abstract class')
103 inherits(HttpError, Error)
109 * Create a constructor for a client error.
113 function createClientErrorConstructor (HttpError, name, code) {
114 var className = name.match(/Error$/) ? name : name + 'Error'
116 function ClientError (message) {
117 // create the error object
118 var err = new Error(message != null ? message : statuses[code])
120 // capture a stack trace to the construction point
121 Error.captureStackTrace(err, ClientError)
123 // adjust the [[Prototype]]
124 setPrototypeOf(err, ClientError.prototype)
126 // redefine the error name
127 Object.defineProperty(err, 'name', {
137 inherits(ClientError, HttpError)
139 ClientError.prototype.status = code
140 ClientError.prototype.statusCode = code
141 ClientError.prototype.expose = true
147 * Create a constructor for a server error.
151 function createServerErrorConstructor (HttpError, name, code) {
152 var className = name.match(/Error$/) ? name : name + 'Error'
154 function ServerError (message) {
155 // create the error object
156 var err = new Error(message != null ? message : statuses[code])
158 // capture a stack trace to the construction point
159 Error.captureStackTrace(err, ServerError)
161 // adjust the [[Prototype]]
162 setPrototypeOf(err, ServerError.prototype)
164 // redefine the error name
165 Object.defineProperty(err, 'name', {
175 inherits(ServerError, HttpError)
177 ServerError.prototype.status = code
178 ServerError.prototype.statusCode = code
179 ServerError.prototype.expose = false
185 * Populate the exports object with constructors for every error class.
189 function populateConstructorExports (exports, codes, HttpError) {
190 codes.forEach(function forEachCode (code) {
192 var name = toIdentifier(statuses[code])
194 switch (String(code).charAt(0)) {
196 CodeError = createClientErrorConstructor(HttpError, name, code)
199 CodeError = createServerErrorConstructor(HttpError, name, code)
204 // export the constructor
205 exports[code] = CodeError
206 exports[name] = CodeError
210 // backwards-compatibility
211 exports["I'mateapot"] = exports.ImATeapot
215 * Convert a string of words to a JavaScript identifier.
219 function toIdentifier (str) {
220 return str.split(' ').map(function (token) {
221 return token.slice(0, 1).toUpperCase() + token.slice(1)
222 }).join('').replace(/[^ _0-9a-z]/gi, '')