mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Preserve case of user-provided http headers in request node
Fixes #3081
This commit is contained in:
parent
775181f761
commit
6e69cfbca4
@ -171,8 +171,23 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
|||||||
opts.timeout = msg.requestTimeout;
|
opts.timeout = msg.requestTimeout;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const originalHeaderMap = {};
|
||||||
|
|
||||||
opts.hooks = {
|
opts.hooks = {
|
||||||
|
beforeRequest: [
|
||||||
|
options => {
|
||||||
|
// Whilst HTTP headers are meant to be case-insensitive,
|
||||||
|
// in the real world, there are servers that aren't so compliant.
|
||||||
|
// GOT will lower case all headers given a chance, so we need
|
||||||
|
// to restore the case of any headers the user has set.
|
||||||
|
Object.keys(options.headers).forEach(h => {
|
||||||
|
if (originalHeaderMap[h] && originalHeaderMap[h] !== h) {
|
||||||
|
options.headers[originalHeaderMap[h]] = options.headers[h];
|
||||||
|
delete options.headers[h];
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
],
|
||||||
beforeRedirect: [
|
beforeRedirect: [
|
||||||
(options, response) => {
|
(options, response) => {
|
||||||
let redirectInfo = {
|
let redirectInfo = {
|
||||||
@ -283,7 +298,7 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
|||||||
})
|
})
|
||||||
if (normalisedHeaders['www-authenticate']) {
|
if (normalisedHeaders['www-authenticate']) {
|
||||||
let authHeader = buildDigestHeader(digestCreds.user,digestCreds.password, options.method, requestUrl.pathname, normalisedHeaders['www-authenticate'])
|
let authHeader = buildDigestHeader(digestCreds.user,digestCreds.password, options.method, requestUrl.pathname, normalisedHeaders['www-authenticate'])
|
||||||
options.headers.authorization = authHeader;
|
options.headers.Authorization = authHeader;
|
||||||
}
|
}
|
||||||
sentCreds = true;
|
sentCreds = true;
|
||||||
return retry(options);
|
return retry(options);
|
||||||
@ -439,6 +454,14 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
|||||||
opts.https = { rejectUnauthorized: msg.rejectUnauthorized };
|
opts.https = { rejectUnauthorized: msg.rejectUnauthorized };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now we have established all of our own headers, take a snapshot
|
||||||
|
// of their case so we can restore it prior to the request being sent.
|
||||||
|
if (opts.headers) {
|
||||||
|
Object.keys(opts.headers).forEach(h => {
|
||||||
|
originalHeaderMap[h.toLowerCase()] = h
|
||||||
|
})
|
||||||
|
}
|
||||||
got(url,opts).then(res => {
|
got(url,opts).then(res => {
|
||||||
msg.statusCode = res.statusCode;
|
msg.statusCode = res.statusCode;
|
||||||
msg.headers = res.headers;
|
msg.headers = res.headers;
|
||||||
|
@ -270,6 +270,16 @@ describe('HTTP Request Node', function() {
|
|||||||
testApp.get('/returnError/:code', function(req,res) {
|
testApp.get('/returnError/:code', function(req,res) {
|
||||||
res.status(parseInt(req.params.code)).json({gotError:req.params.code});
|
res.status(parseInt(req.params.code)).json({gotError:req.params.code});
|
||||||
})
|
})
|
||||||
|
|
||||||
|
testApp.get('/rawHeaders', function(req,res) {
|
||||||
|
const result = {};
|
||||||
|
for (let i=0;i<req.rawHeaders.length;i++) {
|
||||||
|
result[req.rawHeaders[i]] = req.rawHeaders[i+1]
|
||||||
|
}
|
||||||
|
res.json({
|
||||||
|
headers:result
|
||||||
|
});
|
||||||
|
})
|
||||||
startServer(function(err) {
|
startServer(function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
done(err);
|
done(err);
|
||||||
@ -1348,6 +1358,8 @@ describe('HTTP Request Node', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should convert all HTTP headers into lower case', function(done) {
|
it('should convert all HTTP headers into lower case', function(done) {
|
||||||
|
// This is a bad test. Express lower-cases headers in the `req.headers` object,
|
||||||
|
// so this is actually testing express, not the original request.
|
||||||
var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"POST",ret:"obj",url:getTestURL('/postInspect')},
|
var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"POST",ret:"obj",url:getTestURL('/postInspect')},
|
||||||
{id:"n2", type:"helper"}];
|
{id:"n2", type:"helper"}];
|
||||||
helper.load(httpRequestNode, flow, function() {
|
helper.load(httpRequestNode, flow, function() {
|
||||||
@ -1369,6 +1381,26 @@ describe('HTTP Request Node', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should keep HTTP header case as provided by the user', function(done) {
|
||||||
|
var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/rawHeaders')},
|
||||||
|
{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.should.have.property('statusCode',200);
|
||||||
|
msg.payload.should.have.property('headers');
|
||||||
|
msg.payload.headers.should.have.property('Content-Type').which.startWith('text/plain');
|
||||||
|
msg.payload.headers.should.have.property('X-Test-HEAD', "foo");
|
||||||
|
done();
|
||||||
|
} catch(err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
n1.receive({payload:"foo", headers: { 'Content-Type':'text/plain', "X-Test-HEAD": "foo"}});
|
||||||
|
});
|
||||||
|
});
|
||||||
it('should receive HTTP header', function(done) {
|
it('should receive HTTP header', function(done) {
|
||||||
var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"txt",url:getTestURL('/headersInspect')},
|
var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"txt",url:getTestURL('/headersInspect')},
|
||||||
{id:"n2", type:"helper"}];
|
{id:"n2", type:"helper"}];
|
||||||
|
Loading…
Reference in New Issue
Block a user