1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Merge pull request #3465 from node-red/tcp-node-better-split

TCP node better split
This commit is contained in:
Nick O'Leary 2022-04-20 09:34:36 +01:00 committed by GitHub
commit a1e9a14ef3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 41 additions and 10 deletions

View File

@ -50,7 +50,8 @@
</div> </div>
<div id="node-row-newline" class="form-row hidden" style="padding-left:110px;"> <div id="node-row-newline" class="form-row hidden" style="padding-left:110px;">
<span data-i18n="tcpin.label.delimited"></span> <input type="text" id="node-input-newline" style="width:110px;" data-i18n="[placeholder]tcpin.label.optional"> <span data-i18n="tcpin.label.delimited"></span> <input type="text" id="node-input-newline" style="width:110px;" data-i18n="[placeholder]tcpin.label.optional"><br/>
<input type="checkbox" id="node-input-trim" style="display:inline-block; width:auto; vertical-align:top;"> <span data-i18n="tcpin.label.reattach"></span>
</div> </div>
<div class="form-row"> <div class="form-row">
@ -76,6 +77,7 @@
datatype:{value:"buffer"}, datatype:{value:"buffer"},
newline:{value:""}, newline:{value:""},
topic: {value:""}, topic: {value:""},
trim: {value:false},
base64: {/*deprecated*/ value:false, required:true}, base64: {/*deprecated*/ value:false, required:true},
tls: {type:"tls-config", value:'', required:false} tls: {type:"tls-config", value:'', required:false}
}, },
@ -286,7 +288,8 @@
<span id="node-units"></span> <span id="node-units"></span>
</div> </div>
<div id="node-row-newline" class="form-row hidden" style="padding-left:162px;"> <div id="node-row-newline" class="form-row hidden" style="padding-left:162px;">
<span data-i18n="tcpin.label.delimited"></span> <input type="text" id="node-input-newline" style="width:110px;" data-i18n="[placeholder]tcpin.label.optional"> <span data-i18n="tcpin.label.delimited"></span> <input type="text" id="node-input-newline" style="width:110px;" data-i18n="[placeholder]tcpin.label.optional"><br/>
<input type="checkbox" id="node-input-trim" style="display:inline-block; width:auto; vertical-align:top;"> <span data-i18n="tcpin.label.reattach"></span>
</div> </div>
<div class="form-row"> <div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label> <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
@ -306,6 +309,7 @@
ret: {value:"buffer"}, ret: {value:"buffer"},
splitc: {value:"0", required:true}, splitc: {value:"0", required:true},
newline: {value:""}, newline: {value:""},
trim: {value:false},
tls: {type:"tls-config", value:'', required:false} tls: {type:"tls-config", value:'', required:false}
}, },
inputs:1, inputs:1,

View File

@ -88,6 +88,7 @@ module.exports = function(RED) {
this.datatype = n.datatype||'buffer'; /* buffer,utf8,base64 */ this.datatype = n.datatype||'buffer'; /* buffer,utf8,base64 */
this.newline = (n.newline||"").replace("\\n","\n").replace("\\r","\r").replace("\\t","\t"); this.newline = (n.newline||"").replace("\\n","\n").replace("\\r","\r").replace("\\t","\t");
this.base64 = n.base64; this.base64 = n.base64;
this.trim = n.trim || false;
this.server = (typeof n.server == 'boolean')?n.server:(n.server == "server"); this.server = (typeof n.server == 'boolean')?n.server:(n.server == "server");
this.closing = false; this.closing = false;
this.connected = false; this.connected = false;
@ -136,6 +137,7 @@ module.exports = function(RED) {
var parts = buffer.split(node.newline); var parts = buffer.split(node.newline);
for (var i = 0; i<parts.length-1; i+=1) { for (var i = 0; i<parts.length-1; i+=1) {
msg = {topic:node.topic, payload:parts[i]}; msg = {topic:node.topic, payload:parts[i]};
if (node.trim == true) { msg.payload += node.newline; }
msg._session = {type:"tcp",id:id}; msg._session = {type:"tcp",id:id};
node.send(msg); node.send(msg);
} }
@ -230,6 +232,7 @@ module.exports = function(RED) {
var parts = buffer.split(node.newline); var parts = buffer.split(node.newline);
for (var i = 0; i<parts.length-1; i+=1) { for (var i = 0; i<parts.length-1; i+=1) {
msg = {topic:node.topic, payload:parts[i], ip:socket.remoteAddress, port:socket.remotePort}; msg = {topic:node.topic, payload:parts[i], ip:socket.remoteAddress, port:socket.remotePort};
if (node.trim == true) { msg.payload += node.newline; }
msg._session = {type:"tcp",id:id}; msg._session = {type:"tcp",id:id};
node.send(msg); node.send(msg);
} }
@ -518,6 +521,7 @@ module.exports = function(RED) {
this.out = n.out; this.out = n.out;
this.ret = n.ret || "buffer"; this.ret = n.ret || "buffer";
this.newline = (n.newline||"").replace("\\n","\n").replace("\\r","\r").replace("\\t","\t"); this.newline = (n.newline||"").replace("\\n","\n").replace("\\r","\r").replace("\\t","\t");
this.trim = n.trim || false;
this.splitc = n.splitc; this.splitc = n.splitc;
if (n.tls) { if (n.tls) {
var tlsNode = RED.nodes.getNode(n.tls); var tlsNode = RED.nodes.getNode(n.tls);
@ -653,7 +657,8 @@ module.exports = function(RED) {
let parts = chunk.split(node.newline); let parts = chunk.split(node.newline);
for (var p=0; p<parts.length-1; p+=1) { for (var p=0; p<parts.length-1; p+=1) {
let m = RED.util.cloneMessage(msg); let m = RED.util.cloneMessage(msg);
m.payload = parts[p] + node.newline.trimEnd(); m.payload = parts[p];
if (node.trim == true) { m.payload += node.newline; }
nodeSend(m); nodeSend(m);
} }
chunk = parts[parts.length-1]; chunk = parts[parts.length-1];

View File

@ -587,7 +587,8 @@
"ms": "ms", "ms": "ms",
"chars": "chars", "chars": "chars",
"close": "Close", "close": "Close",
"optional": "(optional)" "optional": "(optional)",
"reattach": "re-attach delimiter"
}, },
"type": { "type": {
"listen": "Listen on", "listen": "Listen on",

View File

@ -127,6 +127,12 @@ describe('TCP in Node', function() {
testTCP0(flow, ["foo\nbar"], ["fo", "bar"], done); testTCP0(flow, ["foo\nbar"], ["fo", "bar"], done);
}); });
it('should recv data (Stream/String/Delimiter:o\\n) and reattach o', function(done) {
var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"stream", datatype:"utf8", newline:"o\n", trim:true, topic:"", base64:false, wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP0(flow, ["foo\nbar"], ["foo\n", "bar"], done);
});
it('should recv data (Stream/String/No delimiter)', function(done) { it('should recv data (Stream/String/No delimiter)', function(done) {
var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"stream", datatype:"utf8", newline:"", topic:"", base64:false, wires:[["n2"]] }, var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"stream", datatype:"utf8", newline:"", topic:"", base64:false, wires:[["n2"]] },
{id:"n2", type:"helper"}]; {id:"n2", type:"helper"}];

View File

@ -278,7 +278,22 @@ describe('TCP Request Node', function() {
payload: "bar<A>\nfoo", payload: "bar<A>\nfoo",
topic: 'boo' topic: 'boo'
}], { }], {
payload: "ACK:foobar<A>", payload: "ACK:foobar",
topic: 'boo'
}, done);
});
it('should send & receive, then keep connection, and split return strings and reattach delimiter', function(done) {
var flow = [{id:"n1", type:"tcp request", server:"localhost", port:port, out:"sit", ret:"string", newline:"<A>\\n", trim:true, wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCPMany(flow, [{
payload: "foo",
topic: 'boo'
}, {
payload: "bar<A>\nfoo",
topic: 'boo'
}], {
payload: "ACK:foobar<A>\n",
topic: 'boo' topic: 'boo'
}, done); }, done);
}); });

View File

@ -45,7 +45,7 @@ describe('JSON node', function() {
msg.payload.employees[0].should.have.property('lastName', 'Smith'); msg.payload.employees[0].should.have.property('lastName', 'Smith');
done(); done();
}); });
var jsonString = '{"employees":[{"firstName":"John", "lastName":"Smith"}]}'; var jsonString = ' {"employees":[{"firstName":"John", "lastName":"Smith"}]}\r\n ';
jn1.receive({payload:jsonString,topic: "bar"}); jn1.receive({payload:jsonString,topic: "bar"});
}); });
}); });
@ -63,7 +63,7 @@ describe('JSON node', function() {
msg.payload.employees[0].should.have.property('lastName', 'Smith'); msg.payload.employees[0].should.have.property('lastName', 'Smith');
done(); done();
}); });
var jsonString = Buffer.from('{"employees":[{"firstName":"John", "lastName":"Smith"}]}'); var jsonString = Buffer.from(' {"employees":[{"firstName":"John", "lastName":"Smith"}]}\r\n ');
jn1.receive({payload:jsonString,topic: "bar"}); jn1.receive({payload:jsonString,topic: "bar"});
}); });
}); });

View File

@ -56,7 +56,7 @@ describe('XML node', function() {
should.equal(msg.payload.employees.lastName[0], 'Smith'); should.equal(msg.payload.employees.lastName[0], 'Smith');
done(); done();
}); });
var string = '<employees><firstName>John</firstName><lastName>Smith</lastName></employees>'; var string = ' <employees><firstName>John</firstName><lastName>Smith</lastName></employees>\r\n ';
n1.receive({payload:string,topic: "bar"}); n1.receive({payload:string,topic: "bar"});
}); });
}); });
@ -76,7 +76,7 @@ describe('XML node', function() {
should.equal(msg.foo.employees.lastName[0], 'Smith'); should.equal(msg.foo.employees.lastName[0], 'Smith');
done(); done();
}); });
var string = '<employees><firstName>John</firstName><lastName>Smith</lastName></employees>'; var string = ' <employees><firstName>John</firstName><lastName>Smith</lastName></employees>\r\n ';
n1.receive({foo:string,topic: "bar"}); n1.receive({foo:string,topic: "bar"});
}); });
}); });
@ -96,7 +96,7 @@ describe('XML node', function() {
should.equal(msg.payload.employees.lastName[0], 'Smith'); should.equal(msg.payload.employees.lastName[0], 'Smith');
done(); done();
}); });
var string = '<employees><firstName>John</firstName><lastName>Smith</lastName></employees>'; var string = ' <employees><firstName>John</firstName><lastName>Smith</lastName></employees>\r\n ';
n1.receive({payload:string, topic:"bar", options:{trim:true}}); n1.receive({payload:string, topic:"bar", options:{trim:true}});
}); });
}); });