Comparing version 1.2.1 to 2.0.0
227
lib/index.js
// Load modules | ||
var Http = require('http'); | ||
var NodeUtil = require('util'); | ||
var Hoek = require('hoek'); | ||
@@ -13,59 +12,46 @@ | ||
exports = module.exports = internals.Boom = function (/* (new Error) or (code, message) */) { | ||
exports.wrap = function (error, statusCode, message) { | ||
Hoek.assert(this instanceof internals.Boom, 'Error must be instantiated using new'); | ||
Hoek.assert(error instanceof Error, 'Cannot wrap non-Error object'); | ||
return (error.isBoom ? error : internals.initialize(error, statusCode || 500, message)); | ||
}; | ||
Error.call(this); | ||
this.isBoom = true; | ||
this.response = { | ||
code: 0, | ||
payload: {}, | ||
headers: {} | ||
// type: 'content-type' | ||
}; | ||
internals.create = function (statusCode, message) { | ||
if (arguments[0] instanceof Error) { | ||
var error = new Error(message ? message : undefined); // Avoids settings null message | ||
internals.initialize(error, statusCode); | ||
return error; | ||
}; | ||
// Error | ||
var error = arguments[0]; | ||
internals.initialize = function (error, statusCode, message) { | ||
this.data = error; | ||
this.stack = error.stack; | ||
this.response.code = error.code || 500; | ||
if (error.message) { | ||
this.message = error.message; | ||
} | ||
} | ||
else { | ||
// code, message | ||
Hoek.assert(!isNaN(parseFloat(statusCode)) && isFinite(statusCode) && statusCode >= 400, 'First argument must be a number (400+):', statusCode); | ||
var code = arguments[0]; | ||
var message = arguments[1]; | ||
error.isBoom = true; | ||
error.data = null; | ||
error.output = { | ||
statusCode: statusCode, | ||
payload: {}, | ||
headers: {} | ||
}; | ||
Hoek.assert(!isNaN(parseFloat(code)) && isFinite(code) && code >= 400, 'First argument must be a number (400+)'); | ||
error.reformat = internals.reformat; | ||
error.reformat(); | ||
this.response.code = code; | ||
if (message) { | ||
this.message = message; | ||
} | ||
if (message) { | ||
error.message = (message + (error.message ? ': ' + error.message : '')); | ||
} | ||
// Response format | ||
this.reformat(); | ||
return this; | ||
return error; | ||
}; | ||
NodeUtil.inherits(internals.Boom, Error); | ||
internals.reformat = function () { | ||
internals.Boom.prototype.reformat = function () { | ||
this.response.payload.code = this.response.code; | ||
this.response.payload.error = Http.STATUS_CODES[this.response.code] || 'Unknown'; | ||
this.output.payload.statusCode = this.output.statusCode; | ||
this.output.payload.error = Http.STATUS_CODES[this.output.statusCode] || 'Unknown'; | ||
if (this.message) { | ||
this.response.payload.message = Hoek.escapeHtml(this.message); // Prevent XSS from error message | ||
this.output.payload.message = Hoek.escapeHtml(this.message); // Prevent XSS from error message | ||
} | ||
@@ -75,44 +61,13 @@ }; | ||
// Return custom keys added to the error root or response.payload | ||
internals.Boom.prototype.decorations = function () { | ||
var decoration = {}; | ||
var rootKeys = Object.keys(this); | ||
for (var i = 0, il = rootKeys.length; i < il; ++i) { | ||
var key = rootKeys[i]; | ||
if (typeof this[key] !== 'function' && | ||
key[0] !== '_' && | ||
['isBoom', 'response', 'message'].indexOf(key) === -1) { | ||
decoration[key] = this[key]; | ||
} | ||
} | ||
var responseKeys = Object.keys(this.response.payload); | ||
for (i = 0, il = responseKeys.length; i < il; ++i) { | ||
var key = responseKeys[i]; | ||
if (['code', 'error', 'message'].indexOf(key) === -1) { | ||
decoration.response = decoration.response || {}; | ||
decoration.response[key] = this.response.payload[key]; | ||
} | ||
} | ||
return decoration; | ||
}; | ||
// 4xx Client Errors | ||
internals.Boom.badRequest = function (message) { | ||
exports.badRequest = function (message) { | ||
return new internals.Boom(400, message); | ||
return internals.create(400, message); | ||
}; | ||
internals.Boom.unauthorized = function (message, scheme, attributes) { // Or function (message, wwwAuthenticate[]) | ||
exports.unauthorized = function (message, scheme, attributes) { // Or function (message, wwwAuthenticate[]) | ||
var err = new internals.Boom(401, message); | ||
var err = internals.create(401, message); | ||
@@ -173,3 +128,3 @@ if (!scheme) { | ||
err.response.headers['WWW-Authenticate'] = wwwAuthenticate; | ||
err.output.headers['WWW-Authenticate'] = wwwAuthenticate; | ||
@@ -180,89 +135,89 @@ return err; | ||
internals.Boom.forbidden = function (message) { | ||
exports.forbidden = function (message) { | ||
return new internals.Boom(403, message); | ||
return internals.create(403, message); | ||
}; | ||
internals.Boom.notFound = function (message) { | ||
exports.notFound = function (message) { | ||
return new internals.Boom(404, message); | ||
return internals.create(404, message); | ||
}; | ||
internals.Boom.methodNotAllowed = function (message) { | ||
exports.methodNotAllowed = function (message) { | ||
return new internals.Boom(405, message); | ||
return internals.create(405, message); | ||
}; | ||
internals.Boom.notAcceptable = function (message) { | ||
exports.notAcceptable = function (message) { | ||
return new internals.Boom(406, message); | ||
return internals.create(406, message); | ||
}; | ||
internals.Boom.proxyAuthRequired = function (message) { | ||
exports.proxyAuthRequired = function (message) { | ||
return new internals.Boom(407, message); | ||
return internals.create(407, message); | ||
}; | ||
internals.Boom.clientTimeout = function (message) { | ||
exports.clientTimeout = function (message) { | ||
return new internals.Boom(408, message); | ||
return internals.create(408, message); | ||
}; | ||
internals.Boom.conflict = function (message) { | ||
exports.conflict = function (message) { | ||
return new internals.Boom(409, message); | ||
return internals.create(409, message); | ||
}; | ||
internals.Boom.resourceGone = function (message) { | ||
exports.resourceGone = function (message) { | ||
return new internals.Boom(410, message); | ||
return internals.create(410, message); | ||
}; | ||
internals.Boom.lengthRequired = function (message) { | ||
exports.lengthRequired = function (message) { | ||
return new internals.Boom(411, message); | ||
return internals.create(411, message); | ||
}; | ||
internals.Boom.preconditionFailed = function (message) { | ||
exports.preconditionFailed = function (message) { | ||
return new internals.Boom(412, message); | ||
return internals.create(412, message); | ||
}; | ||
internals.Boom.entityTooLarge = function (message) { | ||
exports.entityTooLarge = function (message) { | ||
return new internals.Boom(413, message); | ||
return internals.create(413, message); | ||
}; | ||
internals.Boom.uriTooLong = function (message) { | ||
exports.uriTooLong = function (message) { | ||
return new internals.Boom(414, message); | ||
return internals.create(414, message); | ||
}; | ||
internals.Boom.unsupportedMediaType = function (message) { | ||
exports.unsupportedMediaType = function (message) { | ||
return new internals.Boom(415, message); | ||
return internals.create(415, message); | ||
}; | ||
internals.Boom.rangeNotSatisfiable = function (message) { | ||
exports.rangeNotSatisfiable = function (message) { | ||
return new internals.Boom(416, message); | ||
return internals.create(416, message); | ||
}; | ||
internals.Boom.expectationFailed = function (message) { | ||
exports.expectationFailed = function (message) { | ||
return new internals.Boom(417, message); | ||
return internals.create(417, message); | ||
}; | ||
@@ -273,48 +228,42 @@ | ||
internals.Boom.internal = function (message, data, code) { | ||
exports.internal = function (message, data, statusCode) { | ||
var err = new internals.Boom(code || 500, message); | ||
var error = (data instanceof Error ? exports.wrap(data, statusCode, message) : internals.create(statusCode || 500, message)); | ||
if (data && data.stack) { | ||
err.trace = data.stack.split('\n'); | ||
err.outterTrace = Hoek.displayStack(1); | ||
if (data instanceof Error === false) { | ||
error.data = data; | ||
} | ||
else { | ||
err.trace = Hoek.displayStack(1); | ||
} | ||
err.data = data; | ||
err.response.payload.message = 'An internal server error occurred'; // Hide actual error from user | ||
return err; | ||
error.output.payload.message = 'An internal server error occurred'; // Hide actual error from user | ||
return error; | ||
}; | ||
internals.Boom.notImplemented = function (message, data) { | ||
exports.notImplemented = function (message, data) { | ||
return internals.Boom.internal(message, data, 501); | ||
return exports.internal(message, data, 501); | ||
}; | ||
internals.Boom.badGateway = function (message, data) { | ||
exports.badGateway = function (message, data) { | ||
return internals.Boom.internal(message, data, 502); | ||
return exports.internal(message, data, 502); | ||
}; | ||
internals.Boom.serverTimeout = function (message, data) { | ||
exports.serverTimeout = function (message, data) { | ||
return internals.Boom.internal(message, data, 503); | ||
return exports.internal(message, data, 503); | ||
}; | ||
internals.Boom.gatewayTimeout = function (message, data) { | ||
exports.gatewayTimeout = function (message, data) { | ||
return internals.Boom.internal(message, data, 504); | ||
return exports.internal(message, data, 504); | ||
}; | ||
internals.Boom.badImplementation = function (message, data) { | ||
exports.badImplementation = function (message, data) { | ||
var err = internals.Boom.internal(message, data, 500); | ||
var err = exports.internal(message, data, 500); | ||
err.isDeveloperError = true; | ||
@@ -324,21 +273,1 @@ return err; | ||
internals.Boom.passThrough = function (code, payload, contentType, headers) { | ||
var err = new internals.Boom(500, 'Pass-through'); // 500 code is only used to initialize | ||
err.data = { | ||
code: code, | ||
payload: payload, | ||
type: contentType | ||
}; | ||
err.response.code = code; | ||
err.response.type = contentType; | ||
err.response.headers = headers; | ||
err.response.payload = payload; | ||
return err; | ||
}; | ||
{ | ||
"name": "boom", | ||
"description": "HTTP-friendly error objects", | ||
"version": "1.2.1", | ||
"version": "2.0.0", | ||
"repository": "git://github.com/spumko/boom", | ||
@@ -6,0 +6,0 @@ "main": "index", |
@@ -27,9 +27,9 @@ // Load modules | ||
error.xyz = 123; | ||
var err = new Boom(error); | ||
expect(err.data.xyz).to.equal(123); | ||
var err = Boom.wrap(error); | ||
expect(err.xyz).to.equal(123); | ||
expect(err.message).to.equal('ka-boom'); | ||
expect(err.response).to.deep.equal({ | ||
code: 500, | ||
expect(err.output).to.deep.equal({ | ||
statusCode: 500, | ||
payload: { | ||
code: 500, | ||
statusCode: 500, | ||
error: 'Internal Server Error', | ||
@@ -43,16 +43,8 @@ message: 'ka-boom' | ||
describe('#decorations', function () { | ||
describe('#create', function () { | ||
it('returns custom members', function (done) { | ||
it('does not sets null message', function (done) { | ||
var error = Boom.badRequest('Custom'); | ||
error.a1 = 'Have an A1 day'; | ||
error.response.payload.walt = 'heisenberg'; | ||
expect(error.decorations()).to.deep.equal({ | ||
a1: 'Have an A1 day', | ||
response: { | ||
walt: 'heisenberg' | ||
} | ||
}); | ||
var error = Boom.unauthorized(null); | ||
expect(error.output.payload.message).to.not.exist; | ||
done(); | ||
@@ -72,3 +64,3 @@ }); | ||
expect(new Error().isBoom).to.not.exist; | ||
expect((new Error()).isBoom).to.not.exist; | ||
done(); | ||
@@ -80,5 +72,5 @@ }); | ||
it('returns a 400 error code', function (done) { | ||
it('returns a 400 error statusCode', function (done) { | ||
expect(Boom.badRequest().response.code).to.equal(400); | ||
expect(Boom.badRequest().output.statusCode).to.equal(400); | ||
done(); | ||
@@ -96,7 +88,7 @@ }); | ||
it('returns a 401 error code', function (done) { | ||
it('returns a 401 error statusCode', function (done) { | ||
var err = Boom.unauthorized(); | ||
expect(err.response.code).to.equal(401); | ||
expect(err.response.headers).to.deep.equal({}); | ||
expect(err.output.statusCode).to.equal(401); | ||
expect(err.output.headers).to.deep.equal({}); | ||
done(); | ||
@@ -114,4 +106,4 @@ }); | ||
var err = Boom.unauthorized('boom', 'Test'); | ||
expect(err.response.code).to.equal(401); | ||
expect(err.response.headers['WWW-Authenticate']).to.equal('Test error="boom"'); | ||
expect(err.output.statusCode).to.equal(401); | ||
expect(err.output.headers['WWW-Authenticate']).to.equal('Test error="boom"'); | ||
done(); | ||
@@ -123,4 +115,4 @@ }); | ||
var err = Boom.unauthorized('boom', 'Test', { a: 1, b: 'something', c: null, d: 0 }); | ||
expect(err.response.code).to.equal(401); | ||
expect(err.response.headers['WWW-Authenticate']).to.equal('Test a="1", b="something", c="", d="0", error="boom"'); | ||
expect(err.output.statusCode).to.equal(401); | ||
expect(err.output.headers['WWW-Authenticate']).to.equal('Test a="1", b="something", c="", d="0", error="boom"'); | ||
done(); | ||
@@ -146,3 +138,3 @@ }); | ||
var err = Boom.unauthorized('message', ['Basic', 'Example e="1"', 'Another x="3", y="4"']); | ||
expect(err.response.headers['WWW-Authenticate']).to.equal('Basic, Example e="1", Another x="3", y="4"'); | ||
expect(err.output.headers['WWW-Authenticate']).to.equal('Basic, Example e="1", Another x="3", y="4"'); | ||
done(); | ||
@@ -155,5 +147,5 @@ }); | ||
it('returns a 405 error code', function (done) { | ||
it('returns a 405 error statusCode', function (done) { | ||
expect(Boom.methodNotAllowed().response.code).to.equal(405); | ||
expect(Boom.methodNotAllowed().output.statusCode).to.equal(405); | ||
done(); | ||
@@ -172,5 +164,5 @@ }); | ||
it('returns a 406 error code', function (done) { | ||
it('returns a 406 error statusCode', function (done) { | ||
expect(Boom.notAcceptable().response.code).to.equal(406); | ||
expect(Boom.notAcceptable().output.statusCode).to.equal(406); | ||
done(); | ||
@@ -189,5 +181,5 @@ }); | ||
it('returns a 407 error code', function (done) { | ||
it('returns a 407 error statusCode', function (done) { | ||
expect(Boom.proxyAuthRequired().response.code).to.equal(407); | ||
expect(Boom.proxyAuthRequired().output.statusCode).to.equal(407); | ||
done(); | ||
@@ -206,5 +198,5 @@ }); | ||
it('returns a 408 error code', function (done) { | ||
it('returns a 408 error statusCode', function (done) { | ||
expect(Boom.clientTimeout().response.code).to.equal(408); | ||
expect(Boom.clientTimeout().output.statusCode).to.equal(408); | ||
done(); | ||
@@ -223,5 +215,5 @@ }); | ||
it('returns a 409 error code', function (done) { | ||
it('returns a 409 error statusCode', function (done) { | ||
expect(Boom.conflict().response.code).to.equal(409); | ||
expect(Boom.conflict().output.statusCode).to.equal(409); | ||
done(); | ||
@@ -240,5 +232,5 @@ }); | ||
it('returns a 410 error code', function (done) { | ||
it('returns a 410 error statusCode', function (done) { | ||
expect(Boom.resourceGone().response.code).to.equal(410); | ||
expect(Boom.resourceGone().output.statusCode).to.equal(410); | ||
done(); | ||
@@ -257,5 +249,5 @@ }); | ||
it('returns a 411 error code', function (done) { | ||
it('returns a 411 error statusCode', function (done) { | ||
expect(Boom.lengthRequired().response.code).to.equal(411); | ||
expect(Boom.lengthRequired().output.statusCode).to.equal(411); | ||
done(); | ||
@@ -274,5 +266,5 @@ }); | ||
it('returns a 412 error code', function (done) { | ||
it('returns a 412 error statusCode', function (done) { | ||
expect(Boom.preconditionFailed().response.code).to.equal(412); | ||
expect(Boom.preconditionFailed().output.statusCode).to.equal(412); | ||
done(); | ||
@@ -291,5 +283,5 @@ }); | ||
it('returns a 413 error code', function (done) { | ||
it('returns a 413 error statusCode', function (done) { | ||
expect(Boom.entityTooLarge().response.code).to.equal(413); | ||
expect(Boom.entityTooLarge().output.statusCode).to.equal(413); | ||
done(); | ||
@@ -308,5 +300,5 @@ }); | ||
it('returns a 414 error code', function (done) { | ||
it('returns a 414 error statusCode', function (done) { | ||
expect(Boom.uriTooLong().response.code).to.equal(414); | ||
expect(Boom.uriTooLong().output.statusCode).to.equal(414); | ||
done(); | ||
@@ -325,5 +317,5 @@ }); | ||
it('returns a 415 error code', function (done) { | ||
it('returns a 415 error statusCode', function (done) { | ||
expect(Boom.unsupportedMediaType().response.code).to.equal(415); | ||
expect(Boom.unsupportedMediaType().output.statusCode).to.equal(415); | ||
done(); | ||
@@ -342,5 +334,5 @@ }); | ||
it('returns a 416 error code', function (done) { | ||
it('returns a 416 error statusCode', function (done) { | ||
expect(Boom.rangeNotSatisfiable().response.code).to.equal(416); | ||
expect(Boom.rangeNotSatisfiable().output.statusCode).to.equal(416); | ||
done(); | ||
@@ -359,5 +351,5 @@ }); | ||
it('returns a 417 error code', function (done) { | ||
it('returns a 417 error statusCode', function (done) { | ||
expect(Boom.expectationFailed().response.code).to.equal(417); | ||
expect(Boom.expectationFailed().output.statusCode).to.equal(417); | ||
done(); | ||
@@ -376,5 +368,5 @@ }); | ||
it('returns a 503 error code', function (done) { | ||
it('returns a 503 error statusCode', function (done) { | ||
expect(Boom.serverTimeout().response.code).to.equal(503); | ||
expect(Boom.serverTimeout().output.statusCode).to.equal(503); | ||
done(); | ||
@@ -392,5 +384,5 @@ }); | ||
it('returns a 403 error code', function (done) { | ||
it('returns a 403 error statusCode', function (done) { | ||
expect(Boom.forbidden().response.code).to.equal(403); | ||
expect(Boom.forbidden().output.statusCode).to.equal(403); | ||
done(); | ||
@@ -408,5 +400,5 @@ }); | ||
it('returns a 404 error code', function (done) { | ||
it('returns a 404 error statusCode', function (done) { | ||
expect(Boom.notFound().response.code).to.equal(404); | ||
expect(Boom.notFound().output.statusCode).to.equal(404); | ||
done(); | ||
@@ -424,5 +416,5 @@ }); | ||
it('returns a 500 error code', function (done) { | ||
it('returns a 500 error statusCode', function (done) { | ||
expect(Boom.internal().response.code).to.equal(500); | ||
expect(Boom.internal().output.statusCode).to.equal(500); | ||
done(); | ||
@@ -435,3 +427,3 @@ }); | ||
expect(err.message).to.equal('my message'); | ||
expect(err.response.payload.message).to.equal('An internal server error occurred'); | ||
expect(err.output.payload.message).to.equal('An internal server error occurred'); | ||
done(); | ||
@@ -446,17 +438,20 @@ }); | ||
it('uses passed in stack if its available', function (done) { | ||
it('returns an error with composite message', function (done) { | ||
var error = new Error(); | ||
error.stack = 'my stack line\nmy second stack line'; | ||
expect(Boom.internal('my message', error).trace[0]).to.equal('my stack line'); | ||
done(); | ||
try { | ||
JSON.parse('{'); | ||
} | ||
catch (err) { | ||
var boom = Boom.internal('Someting bad', err); | ||
expect(boom.message).to.equal('Someting bad: Unexpected end of input'); | ||
done(); | ||
} | ||
}); | ||
}); | ||
describe('#notImplemented', function () { | ||
it('returns a 501 error code', function (done) { | ||
it('returns a 501 error statusCode', function (done) { | ||
expect(Boom.notImplemented().response.code).to.equal(501); | ||
expect(Boom.notImplemented().output.statusCode).to.equal(501); | ||
done(); | ||
@@ -475,5 +470,5 @@ }); | ||
it('returns a 502 error code', function (done) { | ||
it('returns a 502 error statusCode', function (done) { | ||
expect(Boom.badGateway().response.code).to.equal(502); | ||
expect(Boom.badGateway().output.statusCode).to.equal(502); | ||
done(); | ||
@@ -491,5 +486,5 @@ }); | ||
it('returns a 504 error code', function (done) { | ||
it('returns a 504 error statusCode', function (done) { | ||
expect(Boom.gatewayTimeout().response.code).to.equal(504); | ||
expect(Boom.gatewayTimeout().output.statusCode).to.equal(504); | ||
done(); | ||
@@ -507,6 +502,6 @@ }); | ||
it('returns a 500 error code', function (done) { | ||
it('returns a 500 error statusCode', function (done) { | ||
var err = Boom.badImplementation(); | ||
expect(err.response.code).to.equal(500); | ||
expect(err.output.statusCode).to.equal(500); | ||
expect(err.isDeveloperError).to.equal(true); | ||
@@ -517,44 +512,13 @@ done(); | ||
describe('#passThrough', function () { | ||
it('returns a pass-through error', function (done) { | ||
var err = Boom.passThrough(499, { a: 1 }, 'application/text', { 'X-Test': 'Boom' }); | ||
expect(err.response.code).to.equal(499); | ||
expect(err.message).to.equal('Pass-through'); | ||
expect(err.response).to.deep.equal({ | ||
code: 499, | ||
payload: { a: 1 }, | ||
headers: { 'X-Test': 'Boom' }, | ||
type: 'application/text' | ||
}); | ||
done(); | ||
}); | ||
}); | ||
describe('#reformat', function () { | ||
it('encodes any HTML markup in the response payload', function (done) { | ||
it('enstatusCodes any HTML markup in the response payload', function (done) { | ||
var boom = new Boom(new Error('<script>alert(1)</script>')); | ||
expect(boom.response.payload.message).to.not.contain('<script>'); | ||
var boom = Boom.wrap(new Error('<script>alert(1)</script>')); | ||
expect(boom.output.payload.message).to.not.contain('<script>'); | ||
done(); | ||
}); | ||
}); | ||
describe('Boom subclasses', function () { | ||
it('can be subclassed to create custom errors', function (done) { | ||
function BoomSubclass(err) { | ||
Boom.call(this, err); | ||
this.upcaseMsg = err.message.toUpperCase(); | ||
} | ||
Util.inherits(BoomSubclass, Boom); | ||
var boomSubclass = new BoomSubclass(new Error('foo')); | ||
expect(boomSubclass.upcaseMsg).to.contain('FOO'); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
51745
488