319 lines
7.5 KiB
JavaScript
319 lines
7.5 KiB
JavaScript
// Load modules
|
|
|
|
var Http = require('http');
|
|
var Hoek = require('hoek');
|
|
|
|
|
|
// Declare internals
|
|
|
|
var internals = {};
|
|
|
|
exports.wrap = function (error, statusCode, message) {
|
|
|
|
Hoek.assert(error instanceof Error, 'Cannot wrap non-Error object');
|
|
return (error.isBoom ? error : internals.initialize(error, statusCode || 500, message));
|
|
};
|
|
|
|
|
|
exports.create = function (statusCode, message, data) {
|
|
|
|
return internals.create(statusCode, message, data, exports.create);
|
|
};
|
|
|
|
internals.create = function (statusCode, message, data, ctor) {
|
|
|
|
var error = new Error(message ? message : undefined); // Avoids settings null message
|
|
Error.captureStackTrace(error, ctor); // Filter the stack to our external API
|
|
error.data = data || null;
|
|
internals.initialize(error, statusCode);
|
|
return error;
|
|
};
|
|
|
|
internals.initialize = function (error, statusCode, message) {
|
|
|
|
var numberCode = parseInt(statusCode, 10);
|
|
Hoek.assert(!isNaN(numberCode) && numberCode >= 400, 'First argument must be a number (400+):', statusCode);
|
|
|
|
error.isBoom = true;
|
|
error.isServer = numberCode >= 500;
|
|
|
|
if (!error.hasOwnProperty('data')) {
|
|
error.data = null;
|
|
}
|
|
|
|
error.output = {
|
|
statusCode: numberCode,
|
|
payload: {},
|
|
headers: {}
|
|
};
|
|
|
|
error.reformat = internals.reformat;
|
|
error.reformat();
|
|
|
|
if (!message &&
|
|
!error.message) {
|
|
|
|
message = error.output.payload.error;
|
|
}
|
|
|
|
if (message) {
|
|
error.message = (message + (error.message ? ': ' + error.message : ''));
|
|
}
|
|
|
|
return error;
|
|
};
|
|
|
|
|
|
internals.reformat = function () {
|
|
|
|
this.output.payload.statusCode = this.output.statusCode;
|
|
this.output.payload.error = Http.STATUS_CODES[this.output.statusCode] || 'Unknown';
|
|
|
|
if (this.output.statusCode === 500) {
|
|
this.output.payload.message = 'An internal server error occurred'; // Hide actual error from user
|
|
}
|
|
else if (this.message) {
|
|
this.output.payload.message = this.message;
|
|
}
|
|
};
|
|
|
|
|
|
// 4xx Client Errors
|
|
|
|
exports.badRequest = function (message, data) {
|
|
|
|
return internals.create(400, message, data, exports.badRequest);
|
|
};
|
|
|
|
|
|
exports.unauthorized = function (message, scheme, attributes) { // Or function (message, wwwAuthenticate[])
|
|
|
|
var err = internals.create(401, message, undefined, exports.unauthorized);
|
|
|
|
if (!scheme) {
|
|
return err;
|
|
}
|
|
|
|
var wwwAuthenticate = '';
|
|
var i = 0;
|
|
var il = 0;
|
|
|
|
if (typeof scheme === 'string') {
|
|
|
|
// function (message, scheme, attributes)
|
|
|
|
wwwAuthenticate = scheme;
|
|
|
|
if (attributes || message) {
|
|
err.output.payload.attributes = {};
|
|
}
|
|
|
|
if (attributes) {
|
|
var names = Object.keys(attributes);
|
|
for (i = 0, il = names.length; i < il; ++i) {
|
|
var name = names[i];
|
|
if (i) {
|
|
wwwAuthenticate += ',';
|
|
}
|
|
|
|
var value = attributes[name];
|
|
if (value === null ||
|
|
value === undefined) { // Value can be zero
|
|
|
|
value = '';
|
|
}
|
|
wwwAuthenticate += ' ' + name + '="' + Hoek.escapeHeaderAttribute(value.toString()) + '"';
|
|
err.output.payload.attributes[name] = value;
|
|
}
|
|
}
|
|
|
|
if (message) {
|
|
if (attributes) {
|
|
wwwAuthenticate += ',';
|
|
}
|
|
wwwAuthenticate += ' error="' + Hoek.escapeHeaderAttribute(message) + '"';
|
|
err.output.payload.attributes.error = message;
|
|
}
|
|
else {
|
|
err.isMissing = true;
|
|
}
|
|
}
|
|
else {
|
|
|
|
// function (message, wwwAuthenticate[])
|
|
|
|
var wwwArray = scheme;
|
|
for (i = 0, il = wwwArray.length; i < il; ++i) {
|
|
if (i) {
|
|
wwwAuthenticate += ', ';
|
|
}
|
|
|
|
wwwAuthenticate += wwwArray[i];
|
|
}
|
|
}
|
|
|
|
err.output.headers['WWW-Authenticate'] = wwwAuthenticate;
|
|
|
|
return err;
|
|
};
|
|
|
|
|
|
exports.forbidden = function (message, data) {
|
|
|
|
return internals.create(403, message, data, exports.forbidden);
|
|
};
|
|
|
|
|
|
exports.notFound = function (message, data) {
|
|
|
|
return internals.create(404, message, data, exports.notFound);
|
|
};
|
|
|
|
|
|
exports.methodNotAllowed = function (message, data) {
|
|
|
|
return internals.create(405, message, data, exports.methodNotAllowed);
|
|
};
|
|
|
|
|
|
exports.notAcceptable = function (message, data) {
|
|
|
|
return internals.create(406, message, data, exports.notAcceptable);
|
|
};
|
|
|
|
|
|
exports.proxyAuthRequired = function (message, data) {
|
|
|
|
return internals.create(407, message, data, exports.proxyAuthRequired);
|
|
};
|
|
|
|
|
|
exports.clientTimeout = function (message, data) {
|
|
|
|
return internals.create(408, message, data, exports.clientTimeout);
|
|
};
|
|
|
|
|
|
exports.conflict = function (message, data) {
|
|
|
|
return internals.create(409, message, data, exports.conflict);
|
|
};
|
|
|
|
|
|
exports.resourceGone = function (message, data) {
|
|
|
|
return internals.create(410, message, data, exports.resourceGone);
|
|
};
|
|
|
|
|
|
exports.lengthRequired = function (message, data) {
|
|
|
|
return internals.create(411, message, data, exports.lengthRequired);
|
|
};
|
|
|
|
|
|
exports.preconditionFailed = function (message, data) {
|
|
|
|
return internals.create(412, message, data, exports.preconditionFailed);
|
|
};
|
|
|
|
|
|
exports.entityTooLarge = function (message, data) {
|
|
|
|
return internals.create(413, message, data, exports.entityTooLarge);
|
|
};
|
|
|
|
|
|
exports.uriTooLong = function (message, data) {
|
|
|
|
return internals.create(414, message, data, exports.uriTooLong);
|
|
};
|
|
|
|
|
|
exports.unsupportedMediaType = function (message, data) {
|
|
|
|
return internals.create(415, message, data, exports.unsupportedMediaType);
|
|
};
|
|
|
|
|
|
exports.rangeNotSatisfiable = function (message, data) {
|
|
|
|
return internals.create(416, message, data, exports.rangeNotSatisfiable);
|
|
};
|
|
|
|
|
|
exports.expectationFailed = function (message, data) {
|
|
|
|
return internals.create(417, message, data, exports.expectationFailed);
|
|
};
|
|
|
|
exports.badData = function (message, data) {
|
|
|
|
return internals.create(422, message, data, exports.badData);
|
|
};
|
|
|
|
|
|
exports.preconditionRequired = function (message, data) {
|
|
|
|
return internals.create(428, message, data, exports.preconditionRequired);
|
|
};
|
|
|
|
|
|
exports.tooManyRequests = function (message, data) {
|
|
|
|
return internals.create(429, message, data, exports.tooManyRequests);
|
|
};
|
|
|
|
|
|
// 5xx Server Errors
|
|
|
|
exports.internal = function (message, data, statusCode) {
|
|
|
|
return internals.serverError(message, data, statusCode, exports.internal);
|
|
};
|
|
|
|
internals.serverError = function (message, data, statusCode, ctor) {
|
|
|
|
var error;
|
|
if (data instanceof Error) {
|
|
error = exports.wrap(data, statusCode, message);
|
|
} else {
|
|
error = internals.create(statusCode || 500, message, undefined, ctor);
|
|
error.data = data;
|
|
}
|
|
|
|
return error;
|
|
};
|
|
|
|
|
|
exports.notImplemented = function (message, data) {
|
|
|
|
return internals.serverError(message, data, 501, exports.notImplemented);
|
|
};
|
|
|
|
|
|
exports.badGateway = function (message, data) {
|
|
|
|
return internals.serverError(message, data, 502, exports.badGateway);
|
|
};
|
|
|
|
|
|
exports.serverTimeout = function (message, data) {
|
|
|
|
return internals.serverError(message, data, 503, exports.serverTimeout);
|
|
};
|
|
|
|
|
|
exports.gatewayTimeout = function (message, data) {
|
|
|
|
return internals.serverError(message, data, 504, exports.gatewayTimeout);
|
|
};
|
|
|
|
|
|
exports.badImplementation = function (message, data) {
|
|
|
|
var err = internals.serverError(message, data, 500, exports.badImplementation);
|
|
err.isDeveloperError = true;
|
|
return err;
|
|
};
|