diff --git a/lib/data-builder.js b/lib/data-builder.js index b2be24d..50f6448 100644 --- a/lib/data-builder.js +++ b/lib/data-builder.js @@ -8,7 +8,11 @@ var cloneAllProperties = require('../lib/clone.js'); var httpStatus = require('http-status'); -module.exports = function buildResponseData(err, isDebugMode) { +module.exports = function buildResponseData(err, options) { + // Debugging mode is disabled by default. When turned on (in dev), + // all error properties (including) stack traces are sent in the response + var isDebugMode = options.debug; + if (Array.isArray(err) && isDebugMode) { err = serializeArrayOfErrors(err); } @@ -31,6 +35,9 @@ module.exports = function buildResponseData(err, isDebugMode) { fillInternalError(data, err); } + options.safeFields = options.safeFields || []; + fillSafeFields(data, err, options.safeFields); + return data; }; @@ -76,3 +83,13 @@ function fillBadRequestError(data, err) { function fillInternalError(data, err) { data.message = httpStatus[data.statusCode] || 'Unknown Error'; } + +function fillSafeFields(data, err, safeFields) { + if (!Array.isArray(safeFields)) { + safeFields = [safeFields]; + } + + safeFields.forEach(function(field) { + data[field] = err[field]; + }); +} diff --git a/lib/handler.js b/lib/handler.js index 26eadf6..c37794e 100644 --- a/lib/handler.js +++ b/lib/handler.js @@ -28,10 +28,6 @@ exports = module.exports = function createStrongErrorHandler(options) { debug('Initializing with options %j', options); - // Debugging mode is disabled by default. When turned on (in dev), - // all error properties (including) stack traces are sent in the response - var isDebugMode = options.debug; - // Log all errors via console.error (enabled by default) var logError = options.log !== false ? logToConsole : noop; @@ -49,7 +45,7 @@ exports = module.exports = function createStrongErrorHandler(options) { if (!err.status && !err.statusCode && res.statusCode >= 400) err.statusCode = res.statusCode; - var data = buildResponseData(err, isDebugMode); + var data = buildResponseData(err, options); debug('Response status %s data %j', data.statusCode, data); res.setHeader('X-Content-Type-Options', 'nosniff'); diff --git a/test/handler.test.js b/test/handler.test.js index c95fd56..0636c3f 100644 --- a/test/handler.test.js +++ b/test/handler.test.js @@ -231,6 +231,49 @@ describe('strong-error-handler', function() { }); }); + it('should allow setting safe fields when status=5xx', function(done) { + var error = new ErrorWithProps({ + name: 'Error', + safeField: 'SAFE', + unsafeField: 'UNSAFE', + }); + givenErrorHandlerForError(error, { + safeFields: ['safeField'], + }); + + requestJson().end(function(err, res) { + if (err) return done(err); + + expect(res.body).to.have.property('error'); + expect(res.body.error).to.have.property('safeField', 'SAFE'); + expect(res.body.error).not.to.have.property('unsafeField'); + + done(); + }); + }); + + it('should allow setting safe fields when status=4xx', function(done) { + var error = new ErrorWithProps({ + name: 'Error', + statusCode: 422, + safeField: 'SAFE', + unsafeField: 'UNSAFE', + }); + givenErrorHandlerForError(error, { + safeFields: ['safeField'], + }); + + requestJson().end(function(err, res) { + if (err) return done(err); + + expect(res.body).to.have.property('error'); + expect(res.body.error).to.have.property('safeField', 'SAFE'); + expect(res.body.error).not.to.have.property('unsafeField'); + + done(); + }); + }); + it('contains subset of properties when status=4xx', function(done) { var error = new ErrorWithProps({ name: 'ValidationError',