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

Merge pull request #1884 from node-red-hitachi/dev-redirect-bugfix

Prohibit http-request node from sending cookies to the different domain when redirected
This commit is contained in:
Nick O'Leary 2018-09-17 14:15:18 +01:00 committed by GitHub
commit 5fc3ca0e23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 208 additions and 10 deletions

View File

@ -83,6 +83,7 @@ module.exports = function(RED) {
opts.headers = {}; opts.headers = {};
opts.encoding = null; // Force NodeJs to return a Buffer (instead of a string) opts.encoding = null; // Force NodeJs to return a Buffer (instead of a string)
opts.maxRedirects = 21; opts.maxRedirects = 21;
opts.jar = request.jar();
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) {
@ -113,27 +114,41 @@ module.exports = function(RED) {
if (msg.hasOwnProperty('followRedirects')) { if (msg.hasOwnProperty('followRedirects')) {
opts.followRedirect = msg.followRedirects; opts.followRedirect = msg.followRedirects;
} }
if (msg.cookies) { if (!opts.hasOwnProperty('followRedirect') || opts.followRedirect) {
var cookies = []; opts.followRedirect = function(res) {
if (opts.headers.hasOwnProperty('cookie')) { if (this.headers.cookie) {
cookies.push(opts.headers.cookie); delete this.headers.cookie;
} }
return true;
};
}
if (opts.headers.hasOwnProperty('cookie')) {
var cookies = cookie.parse(opts.headers.cookie);
for (var name in cookies) {
if (cookies.hasOwnProperty(name)) {
if (cookies[name] === null) {
// This case clears a cookie for HTTP In/Response nodes.
// Ignore for this node.
} else {
opts.jar.setCookie(name + '=' + cookies[name], url);
}
}
}
delete opts.headers.cookie;
}
if (msg.cookies) {
for (var name in msg.cookies) { for (var name in msg.cookies) {
if (msg.cookies.hasOwnProperty(name)) { if (msg.cookies.hasOwnProperty(name)) {
if (msg.cookies[name] === null || msg.cookies[name].value === null) { if (msg.cookies[name] === null || msg.cookies[name].value === null) {
// This case clears a cookie for HTTP In/Response nodes. // This case clears a cookie for HTTP In/Response nodes.
// Ignore for this node. // Ignore for this node.
} else if (typeof msg.cookies[name] === 'object') { } else if (typeof msg.cookies[name] === 'object') {
cookies.push(cookie.serialize(name,msg.cookies[name].value)); opts.jar.setCookie(name + '=' + msg.cookies[name].value, url);
} else { } else {
cookies.push(cookie.serialize(name,msg.cookies[name])); opts.jar.setCookie(name + '=' + msg.cookies[name], url);
} }
} }
} }
if (cookies.length > 0) {
opts.headers.cookie = cookies.join("; ");
}
} }
if (this.credentials && this.credentials.user) { if (this.credentials && this.credentials.user) {
opts.auth = { opts.auth = {

View File

@ -46,6 +46,9 @@ describe('HTTP Request Node', function() {
var preEnvNoProxyLowerCase; var preEnvNoProxyLowerCase;
var preEnvNoProxyUpperCase; var preEnvNoProxyUpperCase;
//rediect cookie variables
var receivedCookies = {};
function startServer(done) { function startServer(done) {
testPort += 1; testPort += 1;
testServer = stoppable(http.createServer(testApp)); testServer = stoppable(http.createServer(testApp));
@ -98,6 +101,10 @@ describe('HTTP Request Node', function() {
return "https://localhost:"+testSslPort+url; return "https://localhost:"+testSslPort+url;
} }
function getDifferentTestURL(url) {
return "http://127.0.0.1:"+testPort+url;
}
function getSslTestURLWithoutProtocol(url) { function getSslTestURLWithoutProtocol(url) {
return "localhost:"+testSslPort+url; return "localhost:"+testSslPort+url;
} }
@ -182,6 +189,24 @@ describe('HTTP Request Node', function() {
testApp.options('/*', function(req,res) { testApp.options('/*', function(req,res) {
res.status(200).end(); res.status(200).end();
}); });
testApp.get('/redirectToSameDomain', function(req, res) {
var key = req.headers.host + req.url;
receivedCookies[key] = req.cookies;
res.cookie('redirectToSameDomainCookie','same1');
res.redirect(getTestURL('/redirectReturn'));
});
testApp.get('/redirectToDifferentDomain', function(req, res) {
var key = req.headers.host + req.url;
receivedCookies[key] = req.cookies;
res.cookie('redirectToDifferentDomain','different1');
res.redirect(getDifferentTestURL('/redirectReturn'));
});
testApp.get('/redirectReturn', function(req, res) {
var key = req.headers.host + req.url;
receivedCookies[key] = req.cookies;
res.cookie('redirectReturn','return1');
res.status(200).end();
});
startServer(function(err) { startServer(function(err) {
if (err) { if (err) {
done(err); done(err);
@ -1240,4 +1265,162 @@ describe('HTTP Request Node', function() {
}); });
}); });
}); });
describe('redirect-cookie', function() {
it('should send cookies to the same domain when redirected(no cookies)', function(done) {
var flow = [{id:'n1',type:'http request',wires:[['n2']],method:'GET',ret:'obj',url:getTestURL('/redirectToSameDomain')},
{id:"n2", type:"helper"}];
receivedCookies = {};
helper.load(httpRequestNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
var cookies1 = receivedCookies['localhost:'+testPort+'/redirectToSameDomain'];
var cookies2 = receivedCookies['localhost:'+testPort+'/redirectReturn'];
if (cookies1 && Object.keys(cookies1).length != 0) {
done(new Error('Invalid cookie(path:/rediectToSame)'));
return;
}
if ((cookies2 && Object.keys(cookies2).length != 1) ||
cookies2['redirectToSameDomainCookie'] !== 'same1') {
done(new Error('Invalid cookie(path:/rediectReurn)'));
return;
}
done();
});
n1.receive({});
});
});
it('should not send cookies to the different domain when redirected(no cookies)', function(done) {
var flow = [{id:'n1',type:'http request',wires:[['n2']],method:'GET',ret:'obj',url:getTestURL('/redirectToDifferentDomain')},
{id:"n2", type:"helper"}];
receivedCookies = {};
helper.load(httpRequestNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
var cookies1 = receivedCookies['localhost:'+testPort+'/redirectToSameDomain'];
var cookies2 = receivedCookies['127.0.0.1:'+testPort+'/redirectReturn'];
if (cookies1 && Object.keys(cookies1).length != 0) {
done(new Error('Invalid cookie(path:/rediectToDiffer)'));
return;
}
if (cookies2 && Object.keys(cookies2).length != 0) {
done(new Error('Invalid cookie(path:/rediectReurn)'));
return;
}
done();
});
n1.receive({});
});
});
it('should send cookies to the same domain when redirected(msg.cookies)', function(done) {
var flow = [{id:'n1',type:'http request',wires:[['n2']],method:'GET',ret:'obj',url:getTestURL('/redirectToSameDomain')},
{id:"n2", type:"helper"}];
receivedCookies = {};
helper.load(httpRequestNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
var cookies1 = receivedCookies['localhost:'+testPort+'/redirectToSameDomain'];
var cookies2 = receivedCookies['localhost:'+testPort+'/redirectReturn'];
if ((cookies1 && Object.keys(cookies1).length != 1) ||
cookies1['requestCookie'] !== 'request1') {
done(new Error('Invalid cookie(path:/rediectToSame)'));
return;
}
if ((cookies2 && Object.keys(cookies2).length != 2) ||
cookies1['requestCookie'] !== 'request1' ||
cookies2['redirectToSameDomainCookie'] !== 'same1') {
done(new Error('Invalid cookie(path:/rediectReurn)'));
return;
}
done();
});
n1.receive({
cookies: { requestCookie: 'request1' }
});
});
});
it('should not send cookies to the different domain when redirected(msg.cookies)', function(done) {
var flow = [{id:'n1',type:'http request',wires:[['n2']],method:'GET',ret:'obj',url:getTestURL('/redirectToDifferentDomain')},
{id:"n2", type:"helper"}];
receivedCookies = {};
helper.load(httpRequestNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
var cookies1 = receivedCookies['localhost:'+testPort+'/redirectToDifferentDomain'];
var cookies2 = receivedCookies['127.0.0.1:'+testPort+'/redirectReturn'];
if ((cookies1 && Object.keys(cookies1).length != 1) ||
cookies1['requestCookie'] !== 'request1') {
done(new Error('Invalid cookie(path:/rediectToDiffer)'));
return;
}
if (cookies2 && Object.keys(cookies2).length != 0) {
done(new Error('Invalid cookie(path:/rediectReurn)'));
return;
}
done();
});
n1.receive({
cookies: { requestCookie: 'request1' }
});
});
});
it('should send cookies to the same domain when redirected(msg.headers.cookie)', function(done) {
var flow = [{id:'n1',type:'http request',wires:[['n2']],method:'GET',ret:'obj',url:getTestURL('/redirectToSameDomain')},
{id:"n2", type:"helper"}];
receivedCookies = {};
helper.load(httpRequestNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
var cookies1 = receivedCookies['localhost:'+testPort+'/redirectToSameDomain'];
var cookies2 = receivedCookies['localhost:'+testPort+'/redirectReturn'];
if ((cookies1 && Object.keys(cookies1).length != 1) ||
cookies1['requestCookie'] !== 'request1') {
done(new Error('Invalid cookie(path:/rediectToSame)'));
return;
}
if ((cookies2 && Object.keys(cookies2).length != 2) ||
cookies1['requestCookie'] !== 'request1' ||
cookies2['redirectToSameDomainCookie'] !== 'same1') {
done(new Error('Invalid cookie(path:/rediectReurn)'));
return;
}
done();
});
n1.receive({
headers: { cookie: 'requestCookie=request1' }
});
});
});
it('should not send cookies to the different domain when redirected(msg.headers.cookie)', function(done) {
var flow = [{id:'n1',type:'http request',wires:[['n2']],method:'GET',ret:'obj',url:getTestURL('/redirectToDifferentDomain')},
{id:"n2", type:"helper"}];
receivedCookies = {};
helper.load(httpRequestNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
var cookies1 = receivedCookies['localhost:'+testPort+'/redirectToDifferentDomain'];
var cookies2 = receivedCookies['127.0.0.1:'+testPort+'/redirectReturn'];
if ((cookies1 && Object.keys(cookies1).length != 1) ||
cookies1['requestCookie'] !== 'request1') {
done(new Error('Invalid cookie(path:/rediectToDiffer)'));
return;
}
if (cookies2 && Object.keys(cookies2).length != 0) {
done(new Error('Invalid cookie(path:/rediectReurn)'));
return;
}
done();
});
n1.receive({
headers: { cookie: 'requestCookie=request1' }
});
});
});
});
}); });