From 6e69cfbca4b8905e8e315516785afd860fda5f0d Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Fri, 23 Jul 2021 09:55:32 +0100 Subject: [PATCH] Preserve case of user-provided http headers in request node Fixes #3081 --- .../nodes/core/network/21-httprequest.js | 25 ++++++++++++++- .../nodes/core/network/21-httprequest_spec.js | 32 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/packages/node_modules/@node-red/nodes/core/network/21-httprequest.js b/packages/node_modules/@node-red/nodes/core/network/21-httprequest.js index 87495a797..692f5de8c 100644 --- a/packages/node_modules/@node-red/nodes/core/network/21-httprequest.js +++ b/packages/node_modules/@node-red/nodes/core/network/21-httprequest.js @@ -171,8 +171,23 @@ in your Node-RED user directory (${RED.settings.userDir}). opts.timeout = msg.requestTimeout; } } + const originalHeaderMap = {}; 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: [ (options, response) => { let redirectInfo = { @@ -283,7 +298,7 @@ in your Node-RED user directory (${RED.settings.userDir}). }) if (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; return retry(options); @@ -439,6 +454,14 @@ in your Node-RED user directory (${RED.settings.userDir}). 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 => { msg.statusCode = res.statusCode; msg.headers = res.headers; diff --git a/test/nodes/core/network/21-httprequest_spec.js b/test/nodes/core/network/21-httprequest_spec.js index 62b45b3ad..e6610ecb6 100644 --- a/test/nodes/core/network/21-httprequest_spec.js +++ b/test/nodes/core/network/21-httprequest_spec.js @@ -270,6 +270,16 @@ describe('HTTP Request Node', function() { testApp.get('/returnError/:code', function(req,res) { res.status(parseInt(req.params.code)).json({gotError:req.params.code}); }) + + testApp.get('/rawHeaders', function(req,res) { + const result = {}; + for (let i=0;i