Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 20 additions & 13 deletions lib/data-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ module.exports = function buildResponseData(err, isDebugMode) {
fillStatusCode(data, err);

if (typeof err !== 'object') {
data.statusCode = 500;
data.message = '' + err;
err = {};
err = {
statusCode: 500,
message: '' + err,
};
}

if (isDebugMode) {
Expand All @@ -41,10 +42,8 @@ function serializeArrayOfErrors(errors) {
continue;
}

var data = {stack: err.stack};
for (var p in err) { // eslint-disable-line one-var
data[p] = err[p];
}
var data = {};
cloneAllProperties(data, err);
details.push(data);
}

Expand All @@ -63,12 +62,7 @@ function fillStatusCode(data, err) {
}

function fillDebugData(data, err) {
for (var p in err) {
if ((p in data)) continue;
data[p] = err[p];
}
// NOTE err.stack is not an enumerable property
data.stack = err.stack;
cloneAllProperties(data, err);
}

function fillBadRequestError(data, err) {
Expand All @@ -80,3 +74,16 @@ function fillBadRequestError(data, err) {
function fillInternalError(data, err) {
data.message = httpStatus[data.statusCode] || 'Unknown Error';
}

function cloneAllProperties(data, err) {
// NOTE err.name and err.message are not enumerable properties
data.name = err.name;
data.message = err.message;
for (var p in err) {
if ((p in data)) continue;
data[p] = err[p];
}
// NOTE err.stack is not an enumerable property

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a similar note at the top for err.message and err.name.

Also perhaps explain why we are adding stack as the last property, which is to keep the long stack traces at the bottom of the error responses. When the stack trace is in the middle, it is difficult to find the end of the stack trace where the error properties are continued.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added message

// NOTE err.name and err.message are not enumerable properties
// NOTE err.stack is not an enumerable property
// stack is appended last to ensure order is the same for response

// stack is appended last to ensure order is the same for response
data.stack = err.stack;
}
28 changes: 25 additions & 3 deletions test/handler.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ describe('strong-error-handler', function() {
context('JSON response', function() {
it('contains all error properties when debug=true', function(done) {
var error = new ErrorWithProps({
message: 'a test error message',
details: 'some details',
extra: 'sensitive data',
});
Expand All @@ -199,15 +200,36 @@ describe('strong-error-handler', function() {
requestJson().end(function(err, res) {
if (err) return done(err);

var expectedData = {statusCode: 500, stack: error.stack};
for (var key in error) expectedData[key] = error[key];

var expectedData = {
statusCode: 500,
message: 'a test error message',
name: 'ErrorWithProps',
details: 'some details',
extra: 'sensitive data',
stack: error.stack,
};
expect(res.body).to.have.property('error');
expect(res.body.error).to.eql(expectedData);
done();
});
});

it('contains non-enumerable Error properties when debug=true',
function(done) {
var error = new Error('a test error message');
givenErrorHandlerForError(error, {debug: true});
requestJson().end(function(err, res) {
if (err) return done(err);
expect(res.body).to.have.property('error');
var resError = res.body.error;
expect(resError).to.have.property('name', 'Error');
expect(resError).to.have.property('message',
'a test error message');
expect(resError).to.have.property('stack', error.stack);
done();
});
});

it('contains subset of properties when status=4xx', function(done) {
var error = new ErrorWithProps({
name: 'ValidationError',
Expand Down