opusdev/vector-similarity-api
1
1/*!2 * http-errors3 * Copyright(c) 2014 Jonathan Ong4 * Copyright(c) 2016 Douglas Christopher Wilson5 * MIT Licensed6 */7 8'use strict'9 10/**11 * Module dependencies.12 * @private13 */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 * @public24 */25 26module.exports = createError27module.exports.HttpError = createHttpErrorConstructor()28module.exports.isHttpError = createIsHttpErrorFunction(module.exports.HttpError)29 30// Populate exports for all constructors31populateConstructorExports(module.exports, statuses.codes, module.exports.HttpError)32 33/**34 * Get the code class of a status code.35 * @private36 */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 * @public47 */48 49function createError () {50 // so much arity going on ~_~51 var err52 var msg53 var status = 50054 var props = {}55 for (var i = 0; i < arguments.length; i++) {56 var arg = arguments[i]57 var type = typeof arg58 if (type === 'object' && arg instanceof Error) {59 err = arg60 status = err.status || err.statusCode || status61 } else if (type === 'number' && i === 0) {62 status = arg63 } else if (type === 'string') {64 msg = arg65 } else if (type === 'object') {66 props = arg67 } 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 = 50079 }80 81 // constructor82 var HttpError = createError[status] || createError[codeClass(status)]83 84 if (!err) {85 // create error86 err = HttpError87 ? 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 error94 err.expose = status < 50095 err.status = err.statusCode = status96 }97 98 for (var key in props) {99 if (key !== 'status' && key !== 'statusCode') {100 err[key] = props[key]101 }102 }103 104 return err105}106 107/**108 * Create HTTP error abstract base class.109 * @private110 */111 112function createHttpErrorConstructor () {113 function HttpError () {114 throw new TypeError('cannot construct abstract class')115 }116 117 inherits(HttpError, Error)118 119 return HttpError120}121 122/**123 * Create a constructor for a client error.124 * @private125 */126 127function createClientErrorConstructor (HttpError, name, code) {128 var className = toClassName(name)129 130 function ClientError (message) {131 // create the error object132 var msg = message != null ? message : statuses.message[code]133 var err = new Error(msg)134 135 // capture a stack trace to the construction point136 Error.captureStackTrace(err, ClientError)137 138 // adjust the [[Prototype]]139 setPrototypeOf(err, ClientError.prototype)140 141 // redefine the error message142 Object.defineProperty(err, 'message', {143 enumerable: true,144 configurable: true,145 value: msg,146 writable: true147 })148 149 // redefine the error name150 Object.defineProperty(err, 'name', {151 enumerable: false,152 configurable: true,153 value: className,154 writable: true155 })156 157 return err158 }159 160 inherits(ClientError, HttpError)161 nameFunc(ClientError, className)162 163 ClientError.prototype.status = code164 ClientError.prototype.statusCode = code165 ClientError.prototype.expose = true166 167 return ClientError168}169 170/**171 * Create function to test is a value is a HttpError.172 * @private173 */174 175function createIsHttpErrorFunction (HttpError) {176 return function isHttpError (val) {177 if (!val || typeof val !== 'object') {178 return false179 }180 181 if (val instanceof HttpError) {182 return true183 }184 185 return val instanceof Error &&186 typeof val.expose === 'boolean' &&187 typeof val.statusCode === 'number' && val.status === val.statusCode188 }189}190 191/**192 * Create a constructor for a server error.193 * @private194 */195 196function createServerErrorConstructor (HttpError, name, code) {197 var className = toClassName(name)198 199 function ServerError (message) {200 // create the error object201 var msg = message != null ? message : statuses.message[code]202 var err = new Error(msg)203 204 // capture a stack trace to the construction point205 Error.captureStackTrace(err, ServerError)206 207 // adjust the [[Prototype]]208 setPrototypeOf(err, ServerError.prototype)209 210 // redefine the error message211 Object.defineProperty(err, 'message', {212 enumerable: true,213 configurable: true,214 value: msg,215 writable: true216 })217 218 // redefine the error name219 Object.defineProperty(err, 'name', {220 enumerable: false,221 configurable: true,222 value: className,223 writable: true224 })225 226 return err227 }228 229 inherits(ServerError, HttpError)230 nameFunc(ServerError, className)231 232 ServerError.prototype.status = code233 ServerError.prototype.statusCode = code234 ServerError.prototype.expose = false235 236 return ServerError237}238 239/**240 * Set the name of a function, if possible.241 * @private242 */243 244function nameFunc (func, name) {245 var desc = Object.getOwnPropertyDescriptor(func, 'name')246 247 if (desc && desc.configurable) {248 desc.value = name249 Object.defineProperty(func, 'name', desc)250 }251}252 253/**254 * Populate the exports object with constructors for every error class.255 * @private256 */257 258function populateConstructorExports (exports, codes, HttpError) {259 codes.forEach(function forEachCode (code) {260 var CodeError261 var name = toIdentifier(statuses.message[code])262 263 switch (codeClass(code)) {264 case 400:265 CodeError = createClientErrorConstructor(HttpError, name, code)266 break267 case 500:268 CodeError = createServerErrorConstructor(HttpError, name, code)269 break270 }271 272 if (CodeError) {273 // export the constructor274 exports[code] = CodeError275 exports[name] = CodeError276 }277 })278}279 280/**281 * Get a class name from a name identifier.282 *283 * @param {string} name284 * @returns {string}285 * @private286 */287 288function toClassName (name) {289 return name.slice(-5) === 'Error' ? name : name + 'Error'290}291 