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.
Install the module with: npm install restify-errors
In your application, create errors by using the constructors:
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();
});
You can easily do instance checks against the Error objects:
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);
}
}
}
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:
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: ''
// }
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:
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'
// }
Like WError, 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:
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:
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
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:
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');
[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.
This serializer also comes with support for VError's new info
property:
var err = new VError({
name: 'BoomError',
info: {
foo: 'bar',
baz: 1
}
}, 'something bad happened!');
log.error(err, 'oh noes');
[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:
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.
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:
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.
All error constructors are variadic and accept the following signatures:
All VError and WError signatures are also supported, including 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 stringoptions.statusCode
{Number} - an http status codeoptions.restCode
{Number} - a description code for your Error. This is used by restify to render an error when it is directly passed tores.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
.
Creates a custom Error constructor, adds it to the existing exports object.
name
{String} - the name of your Errordefaults
{Object} - an object of default values that will added to the prototype. It is possible to override the defaulttoString()
andtoJSON()
methods.
Returns: {void}
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 codeargs
- arguments to be passed on to the constructor
Returns: {Object} an Error object
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:
make githooks
Before committing, run the prepush hook:
make prepush
If you have style errors, you can auto fix whitespace issues by running:
make codestyle-fix
Copyright (c) 2015 Alex Liu
Licensed under the MIT license.