restify
Version:
REST framework
480 lines (375 loc) • 14.2 kB
Markdown
# restify-errors
[](https://npmjs.org/package/restify-errors)
[](https://travis-ci.org/restify/errors)
[](https://coveralls.io/r/restify/errors?branch=master)
[](https://david-dm.org/restify/errors)
[](https://david-dm.org/restify/errors#info=devDependencies)
[](https://www.bithound.io/github/restify/errors/master)
[](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.