source: node_modules/http-errors/index.js@ d24f17c

main
Last change on this file since d24f17c was d24f17c, checked in by Aleksandar Panovski <apano77@…>, 15 months ago

Initial commit

  • Property mode set to 100644
File size: 6.2 KB
Line 
1/*!
2 * http-errors
3 * Copyright(c) 2014 Jonathan Ong
4 * Copyright(c) 2016 Douglas Christopher Wilson
5 * MIT Licensed
6 */
7
8'use strict'
9
10/**
11 * Module dependencies.
12 * @private
13 */
14
15var deprecate = require('depd')('http-errors')
16var setPrototypeOf = require('setprototypeof')
17var statuses = require('statuses')
18var inherits = require('inherits')
19var toIdentifier = require('toidentifier')
20
21/**
22 * Module exports.
23 * @public
24 */
25
26module.exports = createError
27module.exports.HttpError = createHttpErrorConstructor()
28module.exports.isHttpError = createIsHttpErrorFunction(module.exports.HttpError)
29
30// Populate exports for all constructors
31populateConstructorExports(module.exports, statuses.codes, module.exports.HttpError)
32
33/**
34 * Get the code class of a status code.
35 * @private
36 */
37
38function codeClass (status) {
39 return Number(String(status).charAt(0) + '00')
40}
41
42/**
43 * Create a new HTTP Error.
44 *
45 * @returns {Error}
46 * @public
47 */
48
49function createError () {
50 // so much arity going on ~_~
51 var err
52 var msg
53 var status = 500
54 var props = {}
55 for (var i = 0; i < arguments.length; i++) {
56 var arg = arguments[i]
57 var type = typeof arg
58 if (type === 'object' && arg instanceof Error) {
59 err = arg
60 status = err.status || err.statusCode || status
61 } else if (type === 'number' && i === 0) {
62 status = arg
63 } else if (type === 'string') {
64 msg = arg
65 } else if (type === 'object') {
66 props = arg
67 } else {
68 throw new TypeError('argument #' + (i + 1) + ' unsupported type ' + type)
69 }
70 }
71
72 if (typeof status === 'number' && (status < 400 || status >= 600)) {
73 deprecate('non-error status code; use only 4xx or 5xx status codes')
74 }
75
76 if (typeof status !== 'number' ||
77 (!statuses.message[status] && (status < 400 || status >= 600))) {
78 status = 500
79 }
80
81 // constructor
82 var HttpError = createError[status] || createError[codeClass(status)]
83
84 if (!err) {
85 // create error
86 err = HttpError
87 ? new HttpError(msg)
88 : new Error(msg || statuses.message[status])
89 Error.captureStackTrace(err, createError)
90 }
91
92 if (!HttpError || !(err instanceof HttpError) || err.status !== status) {
93 // add properties to generic error
94 err.expose = status < 500
95 err.status = err.statusCode = status
96 }
97
98 for (var key in props) {
99 if (key !== 'status' && key !== 'statusCode') {
100 err[key] = props[key]
101 }
102 }
103
104 return err
105}
106
107/**
108 * Create HTTP error abstract base class.
109 * @private
110 */
111
112function createHttpErrorConstructor () {
113 function HttpError () {
114 throw new TypeError('cannot construct abstract class')
115 }
116
117 inherits(HttpError, Error)
118
119 return HttpError
120}
121
122/**
123 * Create a constructor for a client error.
124 * @private
125 */
126
127function createClientErrorConstructor (HttpError, name, code) {
128 var className = toClassName(name)
129
130 function ClientError (message) {
131 // create the error object
132 var msg = message != null ? message : statuses.message[code]
133 var err = new Error(msg)
134
135 // capture a stack trace to the construction point
136 Error.captureStackTrace(err, ClientError)
137
138 // adjust the [[Prototype]]
139 setPrototypeOf(err, ClientError.prototype)
140
141 // redefine the error message
142 Object.defineProperty(err, 'message', {
143 enumerable: true,
144 configurable: true,
145 value: msg,
146 writable: true
147 })
148
149 // redefine the error name
150 Object.defineProperty(err, 'name', {
151 enumerable: false,
152 configurable: true,
153 value: className,
154 writable: true
155 })
156
157 return err
158 }
159
160 inherits(ClientError, HttpError)
161 nameFunc(ClientError, className)
162
163 ClientError.prototype.status = code
164 ClientError.prototype.statusCode = code
165 ClientError.prototype.expose = true
166
167 return ClientError
168}
169
170/**
171 * Create function to test is a value is a HttpError.
172 * @private
173 */
174
175function createIsHttpErrorFunction (HttpError) {
176 return function isHttpError (val) {
177 if (!val || typeof val !== 'object') {
178 return false
179 }
180
181 if (val instanceof HttpError) {
182 return true
183 }
184
185 return val instanceof Error &&
186 typeof val.expose === 'boolean' &&
187 typeof val.statusCode === 'number' && val.status === val.statusCode
188 }
189}
190
191/**
192 * Create a constructor for a server error.
193 * @private
194 */
195
196function createServerErrorConstructor (HttpError, name, code) {
197 var className = toClassName(name)
198
199 function ServerError (message) {
200 // create the error object
201 var msg = message != null ? message : statuses.message[code]
202 var err = new Error(msg)
203
204 // capture a stack trace to the construction point
205 Error.captureStackTrace(err, ServerError)
206
207 // adjust the [[Prototype]]
208 setPrototypeOf(err, ServerError.prototype)
209
210 // redefine the error message
211 Object.defineProperty(err, 'message', {
212 enumerable: true,
213 configurable: true,
214 value: msg,
215 writable: true
216 })
217
218 // redefine the error name
219 Object.defineProperty(err, 'name', {
220 enumerable: false,
221 configurable: true,
222 value: className,
223 writable: true
224 })
225
226 return err
227 }
228
229 inherits(ServerError, HttpError)
230 nameFunc(ServerError, className)
231
232 ServerError.prototype.status = code
233 ServerError.prototype.statusCode = code
234 ServerError.prototype.expose = false
235
236 return ServerError
237}
238
239/**
240 * Set the name of a function, if possible.
241 * @private
242 */
243
244function nameFunc (func, name) {
245 var desc = Object.getOwnPropertyDescriptor(func, 'name')
246
247 if (desc && desc.configurable) {
248 desc.value = name
249 Object.defineProperty(func, 'name', desc)
250 }
251}
252
253/**
254 * Populate the exports object with constructors for every error class.
255 * @private
256 */
257
258function populateConstructorExports (exports, codes, HttpError) {
259 codes.forEach(function forEachCode (code) {
260 var CodeError
261 var name = toIdentifier(statuses.message[code])
262
263 switch (codeClass(code)) {
264 case 400:
265 CodeError = createClientErrorConstructor(HttpError, name, code)
266 break
267 case 500:
268 CodeError = createServerErrorConstructor(HttpError, name, code)
269 break
270 }
271
272 if (CodeError) {
273 // export the constructor
274 exports[code] = CodeError
275 exports[name] = CodeError
276 }
277 })
278}
279
280/**
281 * Get a class name from a name identifier.
282 * @private
283 */
284
285function toClassName (name) {
286 return name.substr(-5) !== 'Error'
287 ? name + 'Error'
288 : name
289}
Note: See TracBrowser for help on using the repository browser.