Skip to content

Commit

Permalink
Merge branch 'develop' of github.com:walmartlabs/hapi into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
Eran Hammer committed Oct 22, 2012
2 parents 7167055 + e83ef1c commit f2802f7
Show file tree
Hide file tree
Showing 12 changed files with 681 additions and 461 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ config.json
*/._*
*/*/._*
coverage.*
lib-cov

15 changes: 7 additions & 8 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -249,15 +249,15 @@ function onUnknownRoute(request) {
If a different error format than the default JSON response is required, the server `errors.format` option can be assigned a function to generate a
different error response. The function signature is _'function (result, callback)'_ where:
- _'result'_ - is the **hapi** error object returned by the route handler, and
- _'callback'_ - is the callback function called with the new result object or string.
- _'callback'_ - is a callback function called with the formatted response. The callback function signature is _'function (code, payload, contentType)'_.

For example:
```javascript
var options = {
errors: {
format: function (result, callback) {

callback('Oops: ' + result.message);
callback(500, 'Oops: ' + result.message, 'text/html');
}
}
};
Expand Down Expand Up @@ -701,12 +701,11 @@ In which:
## Response Errors

The 'Hapi.Error' module provides helper methods to generate error responses:
- _'badRequest([message])'_ - HTTP 400 (Bad request).
- _'badRequest([message])'_ - HTTP 400 (Bad Request).
- _'unauthorized([message])'_ - HTTP 401 (Unauthorized).
- _'forbidden([message])'_ - HTTP 403 (Not allowed).
- _'notFound([message])'_ - HTTP 404 (Not found).
- _'internal([message, data])'_ - HTTP 500 (Internal error). The optional _message_ and _data_ values are not returned to the client but are logged internally.
- _'create(message, code, text, [options]) - creates a custom error with the provided _message_, _code_ (the HTTP status code), _text_ (the HTTP status message), and any keys present in _options_.
- _'forbidden([message])'_ - HTTP 403 (Not Allowed).
- _'notFound([message])'_ - HTTP 404 (Not Found).
- _'internal([message, data])'_ - HTTP 500 (Internal Error). The optional _message_ and _data_ values are not returned to the client but are logged internally.

The _message_ value is optional and will be returned to the client in the response unless noted otherwise. For example:

Expand All @@ -719,7 +718,7 @@ function onUnknownRoute(request) {

Error responses are send as JSON payload with the following keys (unless an [error response override](#errors) is configured):
- _code_ - the HTTP status code (e.g. 400).
- _error_ - the HTTP status message (e.g. 'Bad request').
- _error_ - the HTTP status message (e.g. 'Bad Request').
- _message_ - the returned message if provided.

The complete error repsonse including any additional data is added to the request log.
Expand Down
4 changes: 1 addition & 3 deletions lib/cache/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,4 @@ exports.ttl = function (rule, created) {
}

return 0; // Bad rule
};


};
150 changes: 116 additions & 34 deletions lib/error.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Load modules

var Http = require('http');
var NodeUtil = require('util');
var Utils = require('./utils');


Expand All @@ -8,78 +10,158 @@ var Utils = require('./utils');
var internals = {};


exports.badRequest = function (message) {
exports = module.exports = internals.Error = function (code, message, options) {

return exports.create(message, 400, 'Bad request');
Utils.assert(this.constructor === internals.Error, 'Error must be instantiated using new');
Utils.assert(!options || !options.toResponse || typeof options.toResponse === 'function', 'options.toReponse must be a function');
Utils.assert(code >= 400 && code < 600, 'Error code must be 4xx or 5xx');

Error.call(this);

this.name = 'HapiError';
this.code = code;
this.message = message;
this.settings = Utils.clone(options) || {}; // Options can be reused;

return this;
};

NodeUtil.inherits(internals.Error, Error);


internals.Error.prototype.toResponse = function () {

if (this.settings.toResponse) {

return this.settings.toResponse.call(this);
}

var response = {
code: this.code,
payload: {
error: Http.STATUS_CODES[this.code] || 'Unknown',
code: this.code,
message: this.message
}
// contentType: 'application/json'
};

exports.unauthorized = function (message) {
for (var d in this) {
if (this.hasOwnProperty(d) &&
!response.payload.hasOwnProperty(d)) {

return exports.create(message, 401, 'Unauthorized');
response.payload[d] = this[d];
}
}

return response;
};


exports.forbidden = function (message) {
// Utilities

return exports.create(message, 403, 'Not allowed');
internals.Error.badRequest = function (message) {

return new internals.Error(400, message);
};


exports.notFound = function (message) {
internals.Error.unauthorized = function (message) {

return exports.create(message, 404, 'Not Found');
return new internals.Error(401, message);
};


exports.internal = function (message, data) {
internals.Error.forbidden = function (message) {

var custom = {
trace: Utils.callStack(1)
};
return new internals.Error(403, message);
};

if (data) {
custom.data = data;
}

return exports.create(message, 500, 'Internal error', custom);
internals.Error.notFound = function (message) {

return new internals.Error(404, message);
};


exports.format = function (error) {
internals.Error.internal = function (message, data) {

if (error.hasOwnProperty('toResponse') &&
typeof error.toResponse === 'function') {
var format = function () {

return error.toResponse();
}
var response = {
code: 500,
payload: {
error: Http.STATUS_CODES[500],
code: 500,
message: 'An internal server error occurred' // Hide actual error from user
}
};

var err = {
error: error.text,
code: error.code,
message: (error.code >= 500 && error.code < 600 ? 'An internal server error occurred' : error.message)
return response;
};

var err = new internals.Error(500, message, { toResponse: format });
err.trace = Utils.callStack(1);
err.data = data;
return err;
};


exports.create = function (message, code, text, options) {
internals.Error.passThrough = function (code, payload, contentType) {

var format = function () {

var err = new Error();
err.message = message;
err.code = code;
err.text = text;
var response = {
code: code,
payload: payload,
contentType: contentType
};

for (var d in options) {
if (options.hasOwnProperty(d)) {
err[d] = options[d];
return response;
};

var err = new internals.Error(500, 'Pass-through', { toResponse: format }); // 500 code is only used internally and is not exposed when sent

err.passThrough = {
code: code,
payload: payload,
contentType: contentType
};

return err;
};


internals.Error.toResponse = function (err) {

Utils.assert(err instanceof Error, 'Input must be instance of Error');

if (err instanceof internals.Error) {

return err.toResponse();
}

// Other Error

var response = {
code: 500,
payload: {
message: err.message,
name: err.name
}
};

for (var d in err) {
if (err.hasOwnProperty(d)) {
response.payload[d] = err[d];
}
}

return err;
return response;
};






Loading

0 comments on commit f2802f7

Please sign in to comment.