From ef72b5c0f1790e266ae7e39c2fb1c06a12b75c3d Mon Sep 17 00:00:00 2001 From: David Cheung Date: Mon, 16 May 2016 10:57:15 -0400 Subject: [PATCH] Include err.message and err.name for debug data err.message and err.name are not enumerable, therefore needs to be explicited added to the data obj --- lib/data-builder.js | 33 ++++++++++++++++++++------------- test/handler.test.js | 28 +++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/lib/data-builder.js b/lib/data-builder.js index aad5a75..5d3a354 100644 --- a/lib/data-builder.js +++ b/lib/data-builder.js @@ -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) { @@ -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); } @@ -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) { @@ -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 + // stack is appended last to ensure order is the same for response + data.stack = err.stack; +} diff --git a/test/handler.test.js b/test/handler.test.js index a4bda3c..2e834b0 100644 --- a/test/handler.test.js +++ b/test/handler.test.js @@ -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', }); @@ -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',