Merge pull request #2366 from btsimonh/fix-encodeObjecterror

Catches bad objects being encoded, returning instead the error.
This commit is contained in:
Nick O'Leary 2019-11-13 09:33:20 +00:00 committed by GitHub
commit 1f5ff0c6d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 273 additions and 115 deletions

View File

@ -84,9 +84,14 @@ var consoleLogger = function(msg) {
util.log("["+levelNames[msg.level]+"] "+(msg.type?"["+msg.type+":"+(msg.name||msg.id)+"] ":"")+msg.msg.stack);
} else {
var message = msg.msg;
try {
if (typeof message === 'object' && message !== null && message.toString() === '[object Object]' && message.message) {
message = message.message;
}
} catch(e){
message = 'Exception trying to log: '+util.inspect(message);
}
util.log("["+levelNames[msg.level]+"] "+(msg.type?"["+msg.type+":"+(msg.name||msg.id)+"] ":"")+message);
}
}

View File

@ -652,6 +652,7 @@ function normaliseNodeTypeName(name) {
* @memberof @node-red/util_util
*/
function encodeObject(msg,opts) {
try {
var debuglength = 1000;
if (opts && opts.hasOwnProperty('maxLength')) {
debuglength = opts.maxLength;
@ -754,7 +755,7 @@ function encodeObject(msg,opts) {
}," ");
} else {
try { msg.msg = msg.msg.toString(); }
catch(e) { msg.msg = "[Type not printable]"; }
catch(e) { msg.msg = "[Type not printable]" + util.inspect(msg.msg); }
}
}
} else if (msgType === "function") {
@ -776,6 +777,23 @@ function encodeObject(msg,opts) {
}
}
return msg;
} catch(e) {
msg.format = "error";
var errorMsg = {};
if (e.name) {
errorMsg.name = e.name;
}
if (e.hasOwnProperty('message')) {
errorMsg.message = 'encodeObject Error: ['+e.message + '] Value: '+util.inspect(msg.msg);
} else {
errorMsg.message = 'encodeObject Error: ['+e.toString() + '] Value: '+util.inspect(msg.msg);
}
if (errorMsg.message.length > debuglength) {
errorMsg.message = errorMsg.message.substring(0,debuglength);
}
msg.msg = JSON.stringify(errorMsg);
return msg;
}
}
module.exports = {

View File

@ -224,5 +224,29 @@ describe("@node-red/util/log", function() {
});
it('it can log without exception', function() {
var msg = {
msg: {
mystrangeobj:"hello",
},
};
msg.msg.toString = function(){
throw new Error('Exception in toString - should have been caught');
}
msg.msg.constructor = { name: "strangeobj" };
var ret = log.info(msg.msg);
});
it('it can log an object but use .message', function() {
var msg = {
msg: {
message: "my special message",
mystrangeobj:"hello",
},
};
var ret = log.info(msg.msg);
sinon.assert.calledWithMatch(util.log,"my special message");
});
});

View File

@ -772,6 +772,117 @@ describe("@node-red/util/util", function() {
var resultJson = JSON.parse(result.msg);
resultJson.socket.should.eql('[internal]');
});
it('object which fails to serialise', function(done) {
var msg = {
msg: {
obj:{
cantserialise:{
message:'this will not be displayed',
toJSON: function(val) {
throw 'this exception should have been caught';
return 'should not display because we threw first';
},
},
canserialise:{
message:'this should be displayed',
}
},
}
};
var result = util.encodeObject(msg);
result.format.should.eql("error");
var success = (result.msg.indexOf('cantserialise') > 0);
success &= (result.msg.indexOf('this exception should have been caught') > 0);
success &= (result.msg.indexOf('canserialise') > 0);
success.should.eql(1);
done();
});
it('object which fails to serialise - different error type', function(done) {
var msg = {
msg: {
obj:{
cantserialise:{
message:'this will not be displayed',
toJSON: function(val) {
throw new Error('this exception should have been caught');
return 'should not display because we threw first';
},
},
canserialise:{
message:'this should be displayed',
}
},
}
};
var result = util.encodeObject(msg);
result.format.should.eql("error");
var success = (result.msg.indexOf('cantserialise') > 0);
success &= (result.msg.indexOf('this exception should have been caught') > 0);
success &= (result.msg.indexOf('canserialise') > 0);
success.should.eql(1);
done();
});
it('very large object which fails to serialise should be truncated', function(done) {
var msg = {
msg: {
obj:{
big:"",
cantserialise:{
message:'this will not be displayed',
toJSON: function(val) {
throw new Error('this exception should have been caught');
return 'should not display because we threw first';
},
},
canserialise:{
message:'this should be displayed',
}
},
}
};
for (var i = 0; i < 1000; i++) {
msg.msg.obj.big += 'some more string ';
}
var result = util.encodeObject(msg);
result.format.should.eql("error");
var resultJson = JSON.parse(result.msg);
var success = (resultJson.message.length <= 1000);
success.should.eql(true);
done();
});
it('test bad toString', function(done) {
var msg = {
msg: {
mystrangeobj:"hello",
},
};
msg.msg.toString = function(){
throw new Error('Exception in toString - should have been caught');
}
msg.msg.constructor = { name: "strangeobj" };
var result = util.encodeObject(msg);
var success = (result.msg.indexOf('[Type not printable]') >= 0);
success.should.eql(true);
done();
});
it('test bad object constructor', function(done) {
var msg = {
msg: {
mystrangeobj:"hello",
constructor: {
get name(){
throw new Error('Exception in constructor name');
}
}
},
};
var result = util.encodeObject(msg);
done();
});
});
});
});