123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- // Load modules
- var Http = require('http');
- var NodeUtil = require('util');
- var Hoek = require('hoek');
- // Declare internals
- var internals = {};
- exports = module.exports = internals.Boom = function (/* (new Error) or (code, message) */) {
- var self = this;
- Hoek.assert(this.constructor === internals.Boom, 'Error must be instantiated using new');
- Error.call(this);
- this.isBoom = true;
- this.response = {
- code: 0,
- payload: {},
- headers: {}
- // type: 'content-type'
- };
- if (arguments[0] instanceof Error) {
- // Error
- var error = arguments[0];
- this.data = error;
- this.response.code = error.code || 500;
- if (error.message) {
- this.message = error.message;
- }
- }
- else {
- // code, message
- var code = arguments[0];
- var message = arguments[1];
- Hoek.assert(!isNaN(parseFloat(code)) && isFinite(code) && code >= 400, 'First argument must be a number (400+)');
- this.response.code = code;
- if (message) {
- this.message = message;
- }
- }
- // Response format
- this.reformat();
- return this;
- };
- NodeUtil.inherits(internals.Boom, Error);
- internals.Boom.prototype.reformat = function () {
- this.response.payload.code = this.response.code;
- this.response.payload.error = Http.STATUS_CODES[this.response.code] || 'Unknown';
- if (this.message) {
- this.response.payload.message = Hoek.escapeHtml(this.message); // Prevent XSS from error message
- }
- };
- // Utilities
- internals.Boom.badRequest = function (message) {
- return new internals.Boom(400, message);
- };
- internals.Boom.unauthorized = function (message, scheme, attributes) { // Or function (message, wwwAuthenticate[])
- var err = new internals.Boom(401, message);
- if (!scheme) {
- return err;
- }
- var wwwAuthenticate = '';
- if (typeof scheme === 'string') {
- // function (message, scheme, attributes)
- wwwAuthenticate = scheme;
- if (attributes) {
- var names = Object.keys(attributes);
- for (var i = 0, il = names.length; i < il; ++i) {
- if (i) {
- wwwAuthenticate += ',';
- }
- var value = attributes[names[i]];
- if (value === null ||
- value === undefined) { // Value can be zero
- value = '';
- }
- wwwAuthenticate += ' ' + names[i] + '="' + Hoek.escapeHeaderAttribute(value.toString()) + '"';
- }
- }
- if (message) {
- if (attributes) {
- wwwAuthenticate += ',';
- }
- wwwAuthenticate += ' error="' + Hoek.escapeHeaderAttribute(message) + '"';
- }
- else {
- err.isMissing = true;
- }
- }
- else {
- // function (message, wwwAuthenticate[])
- var wwwArray = scheme;
- for (var i = 0, il = wwwArray.length; i < il; ++i) {
- if (i) {
- wwwAuthenticate += ', ';
- }
- wwwAuthenticate += wwwArray[i];
- }
- }
- err.response.headers['WWW-Authenticate'] = wwwAuthenticate;
- return err;
- };
- internals.Boom.clientTimeout = function (message) {
- return new internals.Boom(408, message);
- };
- internals.Boom.serverTimeout = function (message) {
- return new internals.Boom(503, message);
- };
- internals.Boom.forbidden = function (message) {
- return new internals.Boom(403, message);
- };
- internals.Boom.notFound = function (message) {
- return new internals.Boom(404, message);
- };
- internals.Boom.internal = function (message, data) {
- var err = new internals.Boom(500, message);
- if (data && data.stack) {
- err.trace = data.stack.split('\n');
- err.outterTrace = Hoek.displayStack(1);
- }
- 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;
- };
- 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;
- };
|