diff --git a/src/raven.js b/src/raven.js index bc5481353d4a..227d216a0af5 100644 --- a/src/raven.js +++ b/src/raven.js @@ -1754,9 +1754,6 @@ Raven.prototype = { }; } - // If there are no tags/extra, strip the key from the payload alltogther. - if (isEmptyObject(data.tags)) delete data.tags; - if (this._globalContext.user) { // sentry.interfaces.User data.user = this._globalContext.user; @@ -1771,6 +1768,13 @@ Raven.prototype = { // Include server_name if it's defined in globalOptions if (globalOptions.serverName) data.server_name = globalOptions.serverName; + // Cleanup empty properties before sending them to the server + Object.keys(data).forEach(function(key) { + if (data[key] == null || data[key] === '' || isEmptyObject(data[key])) { + delete data[key]; + } + }); + if (isFunction(globalOptions.dataCallback)) { data = globalOptions.dataCallback(data) || data; } diff --git a/src/utils.js b/src/utils.js index 84844b48946e..2839571a6da7 100644 --- a/src/utils.js +++ b/src/utils.js @@ -34,6 +34,10 @@ function isFunction(what) { return typeof what === 'function'; } +function isPlainObject(what) { + return Object.prototype.toString.call(what) === '[object Object]'; +} + function isString(what) { return Object.prototype.toString.call(what) === '[object String]'; } @@ -43,6 +47,8 @@ function isArray(what) { } function isEmptyObject(what) { + if (!isPlainObject(what)) return false; + for (var _ in what) { if (what.hasOwnProperty(_)) { return false; @@ -397,6 +403,7 @@ module.exports = { isErrorEvent: isErrorEvent, isUndefined: isUndefined, isFunction: isFunction, + isPlainObject: isPlainObject, isString: isString, isArray: isArray, isEmptyObject: isEmptyObject, diff --git a/test/raven.test.js b/test/raven.test.js index 105ce594e989..0de30de2430c 100644 --- a/test/raven.test.js +++ b/test/raven.test.js @@ -1136,7 +1136,7 @@ describe('globals', function() { assert.isTrue(Raven._makeRequest.called); }); - it('should strip empty tags', function() { + it('should strip empty attributes', function() { this.sinon.stub(Raven, 'isSetup').returns(true); this.sinon.stub(Raven, '_makeRequest'); this.sinon.stub(Raven, '_getHttpData').returns({ @@ -1148,10 +1148,18 @@ describe('globals', function() { projectId: 2, logger: 'javascript', maxMessageLength: 100, - tags: {} + tags: {}, + extra: {} }; - Raven._send({message: 'bar', tags: {}, extra: {}}); + Raven._send({ + message: 'bar', + tags: {}, + extra: {}, + redundant: '', + attribute: null, + something: undefined + }); assert.deepEqual(Raven._makeRequest.lastCall.args[0].data, { project: '2', logger: 'javascript', diff --git a/test/utils.test.js b/test/utils.test.js index 43f0e38098b7..636e0b1fecae 100644 --- a/test/utils.test.js +++ b/test/utils.test.js @@ -7,6 +7,7 @@ var RavenConfigError = require('../src/configError'); var utils = require('../src/utils'); var isUndefined = utils.isUndefined; var isFunction = utils.isFunction; +var isPlainObject = utils.isPlainObject; var isString = utils.isString; var isArray = utils.isArray; var isObject = utils.isObject; @@ -42,6 +43,20 @@ describe('utils', function() { }); }); + describe('isPlainObject', function() { + it('should do as advertised', function() { + assert.isTrue(isPlainObject({})); + assert.isTrue(isPlainObject({foo: 'bar'})); + assert.isTrue(isPlainObject(new Object())); + assert.isFalse(isPlainObject([])); + assert.isFalse(isPlainObject(undefined)); + assert.isFalse(isPlainObject(null)); + assert.isFalse(isPlainObject(1)); + assert.isFalse(isPlainObject('')); + assert.isFalse(isPlainObject(function() {})); + }); + }); + describe('isString', function() { it('should do as advertised', function() { assert.isTrue(isString(''));