UNPKG

restify

Version:
480 lines (375 loc) 14.2 kB
# restify-errors [![NPM Version](https://img.shields.io/npm/v/restify-errors.svg)](https://npmjs.org/package/restify-errors) [![Build Status](https://travis-ci.org/restify/errors.svg?branch=master)](https://travis-ci.org/restify/errors) [![Coverage Status](https://coveralls.io/repos/restify/errors/badge.svg?branch=master)](https://coveralls.io/r/restify/errors?branch=master) [![Dependency Status](https://david-dm.org/restify/errors.svg)](https://david-dm.org/restify/errors) [![devDependency Status](https://david-dm.org/restify/errors/dev-status.svg)](https://david-dm.org/restify/errors#info=devDependencies) [![bitHound Score](https://www.bithound.io/github/restify/errors/badges/score.svg)](https://www.bithound.io/github/restify/errors/master) [![NSP Status](https://img.shields.io/badge/NSP%20status-no%20vulnerabilities-green.svg)](https://travis-ci.org/restify/errors) > A collection of HTTP and REST Error constructors. The constructors can be used to new up Error objects with default status codes set. The module ships with the following HttpErrors: * 400 BadRequestError * 401 UnauthorizedError * 402 PaymentRequiredError * 403 ForbiddenError * 404 NotFoundError * 405 MethodNotAllowedError * 406 NotAcceptableError * 407 ProxyAuthenticationRequiredError * 408 RequestTimeoutError * 409 ConflictError * 410 GoneError * 411 LengthRequiredError * 412 PreconditionFailedError * 413 RequestEntityTooLargeError * 414 RequesturiTooLargeError * 415 UnsupportedMediaTypeError * 416 RangeNotSatisfiableError (For Node >= 4 & iojs >= 3) * 416 RequestedRangeNotSatisfiableError (For Node 0.x & iojs < 3) * 417 ExpectationFailedError * 418 ImATeapotError * 422 UnprocessableEntityError * 423 LockedError * 424 FailedDependencyError * 425 UnorderedCollectionError * 426 UpgradeRequiredError * 428 PreconditionRequiredError * 429 TooManyRequestsError * 431 RequestHeaderFieldsTooLargeError * 500 InternalServerError * 501 NotImplementedError * 502 BadGatewayError * 503 ServiceUnavailableError * 504 GatewayTimeoutError * 505 HttpVersionNotSupportedError * 506 VariantAlsoNegotiatesError * 507 InsufficientStorageError * 509 BandwidthLimitExceededError * 510 NotExtendedError * 511 NetworkAuthenticationRequiredError and the following RestErrors: * 400 BadDigestError * 405 BadMethodError * 500 InternalError * 409 InvalidArgumentError * 400 InvalidContentError * 401 InvalidCredentialsError * 400 InvalidHeaderError * 400 InvalidVersionError * 409 MissingParameterError * 403 NotAuthorizedError * 412 PreconditionFailedError * 400 RequestExpiredError * 429 RequestThrottledError * 404 ResourceNotFoundError * 406 WrongAcceptError Some of the status codes overlap, since applications can choose the most applicable error type and status code for a given scenario. Should your given scenario require something more customized, the Error objects can be customized with an options object. ## Getting Started Install the module with: `npm install restify-errors` ## Usage ### Creating Errors In your application, create errors by using the constructors: ```js var errors = require('restify-errors'); server.get('/foo', function(req, res, next) { if (!req.query.foo) { return next(new errors.BadRequestError()); } res.send(200, 'ok!'); return next(); }); ``` ### Checking Error types You can easily do instance checks against the Error objects: ```js function redirectIfErr(req, res, next) { var err = req.data.error; if (err) { if (err instanceof errors.InternalServerError) { next(err); } else if (err instanceof errors.NotFoundError) { res.redirect('/NotFound', next); } } } ``` ### Rendering Errors All Error objects in this module are created with a `body` property. restify supports 'rendering' Errors as a response using this property. You can pass Errors to `res.send` and the error will be rendered out as JSON: ```js function render(req, res, next) { res.send(new errors.InternalServerError()); return next(); } // => restify will render an application/json response with an http 500: // { // code: 'InternalServerError', // message: '' // } ``` ### Customizing Errors If you'd like to change the status code or message of a built-in Error, you can pass an options object to the constructor: ```js function render(req, res, next) { var myErr = new errors.InvalidVersionError({ statusCode: 409, message: 'Version not supported with current query params' }); res.send(myErr); return next(); } // => even though InvalidVersionError has a built-in status code of 400, it // has been customized with a 409 status code. restify will now render an // application/json response with an http 409: // { // code: 'InvalidVersionError', // message: 'Version not supported with current query params' // } ``` ### Passing in prior errors (causes) Like [WError](https://github.com/davepacheco/node-verror), all constructors accept an Error object as the first argument to build rich Error objects and stack traces. Assume a previous file lookup failed and an error was passed on: ```js function wrapError(req, res, next) { if (req.error) { var myErr = new errors.InternalServerError(req.error, 'bad times!'); return next(myErr); } return next(); } ``` This will allow Error objects to maintain context from previous errors, giving you full visibility into what caused an underlying issue: ```js console.log(myErr.message); // => 'bad times!' console.log(myErr.toString()); // => InternalServerError: bad times!; caused by Error: file lookup failed! // if you're using Bunyan, you'll get rich stack traces: bunyanLogger.info(myErr); InternalServerError: bad times! at Object.<anonymous> (/Users/restify/test.js:30:16) at Module._compile (module.js:460:26) at Object.Module._extensions..js (module.js:478:10) at Module.load (module.js:355:32) at Function.Module._load (module.js:310:12) at Function.Module.runMain (module.js:501:10) at startup (node.js:129:16) at node.js:814:3 Caused by: Error: file lookup failed! at Object.<anonymous> (/Users/restify/test.js:29:15) at Module._compile (module.js:460:26) at Object.Module._extensions..js (module.js:478:10) at Module.load (module.js:355:32) at Function.Module._load (module.js:310:12) at Function.Module.runMain (module.js:501:10) at startup (node.js:129:16) at node.js:814:3 ``` ### Bunyan support Since errors created via restify-errors inherit from VError, you'll get out of the box support via bunyan's standard serializers. If you are using the `context` property, you can use the serializer shipped with restify-errors: ```js var bunyan = require('bunyan'); var restifyErrors = require('restify-errors'); var log = bunyan.createLogger({ name: 'myLogger', serializers: { err: restifyErrors.bunyanSerializer } }); var err = new restifyErrors.InternalServerError({ message: 'cannot service this request!', context: { foo: 'bar', bar: 1 } }); log.error(err, 'oh noes'); ``` ```sh [2016-08-31T22:27:13.117Z] ERROR: log/51633 on laptop: oh noes (err.code=InternalServer) InternalServerError: cannot service this request! (foo="bar", bar=1) at Object.<anonymous> (/restify/test.js:11:11) at Module._compile (module.js:409:26) at Object.Module._extensions..js (module.js:416:10) at Module.load (module.js:343:32) at Function.Module._load (module.js:300:12) at Function.Module.runMain (module.js:441:10) at startup (node.js:139:18) at node.js:974:3 ``` You can, of course, combine this with the standard set of serializers that bunyan ships with. #### VError support This serializer also comes with support for VError's new `info` property: ```js var err = new VError({ name: 'BoomError', info: { foo: 'bar', baz: 1 } }, 'something bad happened!'); log.error(err, 'oh noes'); ``` ```sh [2016-08-31T22:21:35.900Z] ERROR: log/50874 on laptop: oh noes BoomError: something bad happened! (foo="bar", baz=1) at Object.<anonymous> (/restify/test.js:11:11) at Module._compile (module.js:409:26) at Object.Module._extensions..js (module.js:416:10) at Module.load (module.js:343:32) at Function.Module._load (module.js:300:12) at Function.Module.runMain (module.js:441:10) at startup (node.js:139:18) at node.js:974:3 ``` VError's MultiError is also supported: ```js var underlyingErr = new Error('boom'); var multiErr = new verror.MultiError([ new Error('boom'), new restifyErrors.InternalServerError(underlyingErr, { message: 'wrapped', context: { foo: 'bar', baz: 1 } }) ]); log.error(multiErr, 'oh noes'); ``` ``` [2016-08-31T22:48:43.244Z] ERROR: logger/55311 on laptop: oh noes MultiError 1 of 2: Error: boom at Object.<anonymous> (/restify/test.js:16:5) at Module._compile (module.js:409:26) at Object.Module._extensions..js (module.js:416:10) at Module.load (module.js:343:32) at Function.Module._load (module.js:300:12) at Function.Module.runMain (module.js:441:10) at startup (node.js:139:18) at node.js:974:3 MultiError 2 of 2: InternalServerError: wrapped (foo="bar", baz=1) at Object.<anonymous> (/restify/test.js:17:5) at Module._compile (module.js:409:26) at Object.Module._extensions..js (module.js:416:10) at Module.load (module.js:343:32) at Function.Module._load (module.js:300:12) at Function.Module.runMain (module.js:441:10) at startup (node.js:139:18) at node.js:974:3 Caused by: Error: boom at Object.<anonymous> (/restify/test.js:14:21) at Module._compile (module.js:409:26) at Object.Module._extensions..js (module.js:416:10) at Module.load (module.js:343:32) at Function.Module._load (module.js:300:12) at Function.Module.runMain (module.js:441:10) at startup (node.js:139:18) at node.js:974:3 ``` For more information about building rich errors, check out [VError](https://github.com/davepacheco/node-verror). ### Subclassing Errors You can also create your own Error subclasses by using the provided `makeConstructor()` method. Making a new subclass will add the constructor to the existing exports object: ```js errors.makeConstructor('ExecutionError', { statusCode: 406, failureType: 'motion' }); var myErr = new errors.ExecutionError('bad joystick input!'); console.log(myErr instanceof ExecutionError); // => true console.log(myErr.message); // => 'ExecutionError: bad joystick input!' console.log(myErr.failureType); // => 'motion' console.log(myErr.statusCode); // => 406 console.log(myErr.stack); ExecutionError: bad joystick input! at Object.<anonymous> (/Users/restify/test.js:30:16) at Module._compile (module.js:460:26) at Object.Module._extensions..js (module.js:478:10) at Module.load (module.js:355:32) at Function.Module._load (module.js:310:12) at Function.Module.runMain (module.js:501:10) at startup (node.js:129:16) at node.js:814:3 ``` Custom errors are subclassed from RestError, so you get all the built-in goodness of HttpError/RestError. The constructor returned to you accepts all the same signatures accepted by HttpError/RestError. ## API All error constructors are variadic and accept the following signatures: ### new Error(message) ### new Error(printf, args...) ### new Error(options [, printf, args...]) ### new Error(priorErr, message]) ### new Error(priorErr [, printf, args...]) ### new Error(priorErr, options [, printf, args...]) All [VError and WError](https://github.com/davepacheoco/node-verror) signatures are also supported, including [extsprintf](https://github.com/davepacheco/node-extsprintf). You can pass in a message like a regular error: * `message` {String} - an error message Or pass in an options object for more customization: * `options.message` {String} - an error message string * `options.statusCode` {Number} - an http status code * `options.restCode` {Number} - a description code for your Error. This is used by restify to render an error when it is directly passed to `res.send()`. By default, it is the name of your error constructor (e.g., the restCode for a BadDigestError is BadDigest). * `options.context` {Object} - object of contextual properties relevant to the creation of the error, i.e., the url of a failed http request In all signatures, you can optionally pass in an Error as the first argument, which will cause WError to use it as a prior cause: * `priorErr` {Error} - an Error object **Returns:** {Error} an Error object **IMPORTANT:** If a printf style signature is used, the Error message will prefer that over `options.message`. ### makeConstructor(name [, defaults]) Creates a custom Error constructor, adds it to the existing exports object. * `name` {String} - the name of your Error * `defaults` {Object} - an object of default values that will added to the prototype. It is possible to override the default `toString()` and `toJSON()` methods. **Returns:** {void} ### makeErrFromCode(name [, args...]) Create an Error object using an http status code. This uses `http` module's `STATUS_CODES` to do the status code lookup. Thus, this convenience method is useful only for creating HttpErrors, and not RestErrors. * `statusCode` {Number} - an http status code * `args` - arguments to be passed on to the constructor **Returns:** {Object} an Error object ## Contributing Add unit tests for any new or changed functionality. Ensure that lint and style checks pass. To start contributing, install the git pre-push hooks: ```sh make githooks ``` Before committing, run the prepush hook: ```sh make prepush ``` If you have style errors, you can auto fix whitespace issues by running: ```sh make codestyle-fix ``` ## License Copyright (c) 2015 Alex Liu Licensed under the MIT license.