mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Prevent unmodified msg.headers from breaking HTTP Request flows
Closed #1015
This commit is contained in:
parent
6562c558de
commit
c9317659c5
@ -26,6 +26,7 @@ module.exports = function(RED) {
|
|||||||
var onHeaders = require('on-headers');
|
var onHeaders = require('on-headers');
|
||||||
var typer = require('media-typer');
|
var typer = require('media-typer');
|
||||||
var isUtf8 = require('is-utf8');
|
var isUtf8 = require('is-utf8');
|
||||||
|
var hashSum = require("hash-sum");
|
||||||
|
|
||||||
function rawBodyParser(req, res, next) {
|
function rawBodyParser(req, res, next) {
|
||||||
if (req.skipRawBodyParser) { next(); } // don't parse this if told to skip
|
if (req.skipRawBodyParser) { next(); } // don't parse this if told to skip
|
||||||
@ -276,6 +277,15 @@ module.exports = function(RED) {
|
|||||||
this.on("input",function(msg) {
|
this.on("input",function(msg) {
|
||||||
if (msg.res) {
|
if (msg.res) {
|
||||||
var headers = RED.util.cloneMessage(node.headers);
|
var headers = RED.util.cloneMessage(node.headers);
|
||||||
|
if (msg.headers) {
|
||||||
|
if (msg.headers.hasOwnProperty('x-node-red-request-node')) {
|
||||||
|
var headerHash = msg.headers['x-node-red-request-node'];
|
||||||
|
delete msg.headers['x-node-red-request-node'];
|
||||||
|
var hash = hashSum(msg.headers);
|
||||||
|
if (hash === headerHash) {
|
||||||
|
delete msg.headers;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (msg.headers) {
|
if (msg.headers) {
|
||||||
for (var h in msg.headers) {
|
for (var h in msg.headers) {
|
||||||
if (msg.headers.hasOwnProperty(h) && !headers.hasOwnProperty(h)) {
|
if (msg.headers.hasOwnProperty(h) && !headers.hasOwnProperty(h)) {
|
||||||
@ -283,6 +293,7 @@ module.exports = function(RED) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (Object.keys(headers).length > 0) {
|
if (Object.keys(headers).length > 0) {
|
||||||
msg.res._res.set(headers);
|
msg.res._res.set(headers);
|
||||||
}
|
}
|
||||||
|
@ -108,6 +108,12 @@
|
|||||||
<code>example.com/{{{topic}}}</code>, it will have the value of <code>msg.topic</code> automatically inserted.
|
<code>example.com/{{{topic}}}</code>, it will have the value of <code>msg.topic</code> automatically inserted.
|
||||||
Using {{{...}}} prevents mustache from escaping characters like / & etc.</p>
|
Using {{{...}}} prevents mustache from escaping characters like / & etc.</p>
|
||||||
<p><b>Note</b>: If running behind a proxy, the standard <code>http_proxy=...</code> environment variable should be set and Node-RED restarted.</p>
|
<p><b>Note</b>: If running behind a proxy, the standard <code>http_proxy=...</code> environment variable should be set and Node-RED restarted.</p>
|
||||||
|
<h4>Using multiple HTTP Request nodes</h4>
|
||||||
|
<p>In order to use more than one of these nodes in the same flow, care must be taken with
|
||||||
|
the <code>msg.headers</code> property. The first node will set this property with
|
||||||
|
the response headers. The next node will then use those headers for its request - this
|
||||||
|
is not usually the right thing to do. The <code>msg.headers</code> property <b>must</b>
|
||||||
|
be deleted with a <b>change</b> node in order for the requests to work as expected.</p>
|
||||||
<h4>Cookie handling</h4>
|
<h4>Cookie handling</h4>
|
||||||
<p>The <code>cookies</code> property passed to the node must be an object of name/value pairs.
|
<p>The <code>cookies</code> property passed to the node must be an object of name/value pairs.
|
||||||
The value can be either a string to set the value of the cookie or it can be an
|
The value can be either a string to set the value of the cookie or it can be an
|
||||||
|
@ -22,6 +22,7 @@ module.exports = function(RED) {
|
|||||||
var mustache = require("mustache");
|
var mustache = require("mustache");
|
||||||
var querystring = require("querystring");
|
var querystring = require("querystring");
|
||||||
var cookie = require("cookie");
|
var cookie = require("cookie");
|
||||||
|
var hashSum = require("hash-sum");
|
||||||
|
|
||||||
function HTTPRequest(n) {
|
function HTTPRequest(n) {
|
||||||
RED.nodes.createNode(this,n);
|
RED.nodes.createNode(this,n);
|
||||||
@ -82,6 +83,15 @@ module.exports = function(RED) {
|
|||||||
opts.headers = {};
|
opts.headers = {};
|
||||||
var ctSet = "Content-Type"; // set default camel case
|
var ctSet = "Content-Type"; // set default camel case
|
||||||
var clSet = "Content-Length";
|
var clSet = "Content-Length";
|
||||||
|
if (msg.headers) {
|
||||||
|
if (msg.headers.hasOwnProperty('x-node-red-request-node')) {
|
||||||
|
var headerHash = msg.headers['x-node-red-request-node'];
|
||||||
|
delete msg.headers['x-node-red-request-node'];
|
||||||
|
var hash = hashSum(msg.headers);
|
||||||
|
if (hash === headerHash) {
|
||||||
|
delete msg.headers;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (msg.headers) {
|
if (msg.headers) {
|
||||||
for (var v in msg.headers) {
|
for (var v in msg.headers) {
|
||||||
if (msg.headers.hasOwnProperty(v)) {
|
if (msg.headers.hasOwnProperty(v)) {
|
||||||
@ -97,6 +107,7 @@ module.exports = function(RED) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (msg.cookies) {
|
if (msg.cookies) {
|
||||||
var cookies = [];
|
var cookies = [];
|
||||||
if (opts.headers.hasOwnProperty('cookie')) {
|
if (opts.headers.hasOwnProperty('cookie')) {
|
||||||
@ -207,7 +218,7 @@ module.exports = function(RED) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
msg.headers['x-node-red-request-node'] = hashSum(msg.headers);
|
||||||
// msg.url = url; // revert when warning above finally removed
|
// msg.url = url; // revert when warning above finally removed
|
||||||
res.on('data',function(chunk) {
|
res.on('data',function(chunk) {
|
||||||
if (!Buffer.isBuffer(chunk)) {
|
if (!Buffer.isBuffer(chunk)) {
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
"follow-redirects":"1.2.4",
|
"follow-redirects":"1.2.4",
|
||||||
"fs-extra": "1.0.0",
|
"fs-extra": "1.0.0",
|
||||||
"fs.notify":"0.0.4",
|
"fs.notify":"0.0.4",
|
||||||
|
"hash-sum":"1.0.2",
|
||||||
"i18next":"1.10.6",
|
"i18next":"1.10.6",
|
||||||
"is-utf8":"0.2.1",
|
"is-utf8":"0.2.1",
|
||||||
"js-yaml": "3.8.4",
|
"js-yaml": "3.8.4",
|
||||||
@ -48,7 +49,7 @@
|
|||||||
"mqtt": "2.9.0",
|
"mqtt": "2.9.0",
|
||||||
"multer": "1.3.0",
|
"multer": "1.3.0",
|
||||||
"mustache": "2.3.0",
|
"mustache": "2.3.0",
|
||||||
"nopt": "4.0.1",
|
"nopt": "3.0.6",
|
||||||
"oauth2orize":"1.8.0",
|
"oauth2orize":"1.8.0",
|
||||||
"on-headers":"1.0.1",
|
"on-headers":"1.0.1",
|
||||||
"passport":"0.3.2",
|
"passport":"0.3.2",
|
||||||
|
@ -21,6 +21,7 @@ var express = require("express");
|
|||||||
var bodyParser = require('body-parser');
|
var bodyParser = require('body-parser');
|
||||||
var helper = require("../../helper.js");
|
var helper = require("../../helper.js");
|
||||||
var httpRequestNode = require("../../../../nodes/core/io/21-httprequest.js");
|
var httpRequestNode = require("../../../../nodes/core/io/21-httprequest.js");
|
||||||
|
var hashSum = require("hash-sum");
|
||||||
|
|
||||||
describe('HTTP Request Node', function() {
|
describe('HTTP Request Node', function() {
|
||||||
var testApp;
|
var testApp;
|
||||||
@ -399,4 +400,46 @@ describe('HTTP Request Node', function() {
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('ignores unmodified msg.headers property', function(done) {
|
||||||
|
var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"POST",ret:"obj",url:getTestURL('/postInspect')},
|
||||||
|
{id:"n2", type:"helper"}];
|
||||||
|
helper.load(httpRequestNode, flow, function() {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
n2.on("input", function(msg) {
|
||||||
|
try {
|
||||||
|
msg.payload.headers.should.have.property('content-type').which.startWith('application/json');
|
||||||
|
msg.payload.headers.should.not.have.property('x-node-red-request-node');
|
||||||
|
done();
|
||||||
|
} catch(err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Pass in a headers property with an unmodified x-node-red-request-node hash
|
||||||
|
// This should cause the node to ignore the headers
|
||||||
|
n1.receive({payload:{foo:"bar"}, headers: { 'content-type': 'text/plain', "x-node-red-request-node":"67690139"}});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
it('uses modified msg.headers property', function(done) {
|
||||||
|
var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"POST",ret:"obj",url:getTestURL('/postInspect')},
|
||||||
|
{id:"n2", type:"helper"}];
|
||||||
|
helper.load(httpRequestNode, flow, function() {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
n2.on("input", function(msg) {
|
||||||
|
try {
|
||||||
|
msg.payload.headers.should.have.property('content-type').which.startWith('text/plain');
|
||||||
|
msg.payload.headers.should.not.have.property('x-node-red-request-node');
|
||||||
|
done();
|
||||||
|
} catch(err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Pass in a headers property with a x-node-red-request-node hash that doesn't match the contents
|
||||||
|
// This should cause the node to use the headers
|
||||||
|
n1.receive({payload:{foo:"bar"}, headers: { 'content-type': 'text/plain', "x-node-red-request-node":"INVALID_SUM"}});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user