From 983e6e124eb9557eec55c5f2e2b834a926243955 Mon Sep 17 00:00:00 2001 From: Michael Kret <88898367+michael-radency@users.noreply.github.com> Date: Thu, 27 Apr 2023 13:36:02 +0300 Subject: [PATCH] fix(HTTP Request Node): Always lowercase headers --- .../HttpRequest/V3/HttpRequestV3.node.ts | 21 +++++++---- .../nodes-base/test/utils/utilities.test.ts | 35 ++++++++++++++++++- packages/nodes-base/utils/utilities.ts | 8 +++++ 3 files changed, 57 insertions(+), 7 deletions(-) diff --git a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts index f515b7ab2adb4..da26c925af85b 100644 --- a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts +++ b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts @@ -24,6 +24,7 @@ import { replaceNullValues, sanitizeUiMessage, } from '../GenericFunctions'; +import { keysToLowercase } from '../../../utils/utilities'; function toText(data: T) { if (typeof data === 'object' && data !== null) { @@ -1033,17 +1034,21 @@ export class HttpRequestV3 implements INodeType { const body = this.getNodeParameter('body', itemIndex, '') as string; const sendHeaders = this.getNodeParameter('sendHeaders', itemIndex, false) as boolean; + const headerParameters = this.getNodeParameter( 'headerParameters.parameters', itemIndex, [], ) as [{ name: string; value: string }]; + const specifyHeaders = this.getNodeParameter( 'specifyHeaders', itemIndex, 'keypair', ) as string; + const jsonHeadersParameter = this.getNodeParameter('jsonHeaders', itemIndex, '') as string; + const { redirect, batching, @@ -1221,8 +1226,8 @@ export class HttpRequestV3 implements INodeType { requestOptions.body = uploadData; requestOptions.headers = { ...requestOptions.headers, - 'Content-Length': contentLength, - 'Content-Type': itemBinaryData.mimeType ?? 'application/octet-stream', + 'content-length': contentLength, + 'content-type': itemBinaryData.mimeType ?? 'application/octet-stream', }; } else if (bodyContentType === 'raw') { requestOptions.body = body; @@ -1253,8 +1258,9 @@ export class HttpRequestV3 implements INodeType { // Get parameters defined in the UI if (sendHeaders && headerParameters) { + let additionalHeaders: IDataObject = {}; if (specifyHeaders === 'keypair') { - requestOptions.headers = headerParameters.reduce(parametersToKeyValue, {}); + additionalHeaders = headerParameters.reduce(parametersToKeyValue, {}); } else if (specifyHeaders === 'json') { // body is specified using JSON try { @@ -1269,8 +1275,12 @@ export class HttpRequestV3 implements INodeType { ); } - requestOptions.headers = jsonParse(jsonHeadersParameter); + additionalHeaders = jsonParse(jsonHeadersParameter); } + requestOptions.headers = { + ...requestOptions.headers, + ...keysToLowercase(additionalHeaders), + }; } if (autoDetectResponseFormat || responseFormat === 'file') { @@ -1290,7 +1300,7 @@ export class HttpRequestV3 implements INodeType { requestOptions.headers = {}; } const rawContentType = this.getNodeParameter('rawContentType', itemIndex) as string; - requestOptions.headers['Content-Type'] = rawContentType; + requestOptions.headers['content-type'] = rawContentType; } const authDataKeys: IAuthDataSanitizeKeys = {}; @@ -1338,7 +1348,6 @@ export class HttpRequestV3 implements INodeType { try { this.sendMessageToUI(sanitizeUiMessage(requestOptions, authDataKeys)); } catch (e) {} - if (authentication === 'genericCredentialType' || authentication === 'none') { if (oAuth1Api) { const requestOAuth1 = this.helpers.requestOAuth1.call(this, 'oAuth1Api', requestOptions); diff --git a/packages/nodes-base/test/utils/utilities.test.ts b/packages/nodes-base/test/utils/utilities.test.ts index 78fa5631bc0c5..b99e786f7d0b0 100644 --- a/packages/nodes-base/test/utils/utilities.test.ts +++ b/packages/nodes-base/test/utils/utilities.test.ts @@ -1,4 +1,4 @@ -import { fuzzyCompare } from '../../utils/utilities'; +import { fuzzyCompare, keysToLowercase } from '../../utils/utilities'; //most test cases for fuzzyCompare are done in Compare Datasets node tests describe('Test fuzzyCompare', () => { @@ -29,3 +29,36 @@ describe('Test fuzzyCompare', () => { expect(compareFunction(null, '0')).toEqual(false); }); }); + +describe('Test keysToLowercase', () => { + it('should convert keys to lowercase', () => { + const headers = { + 'Content-Type': 'application/json', + 'X-Test-Header': 'Test', + Accept: 'application/json', + }; + + const newHeaders = keysToLowercase(headers); + + expect(newHeaders).toEqual({ + 'content-type': 'application/json', + 'x-test-header': 'Test', + accept: 'application/json', + }); + }); + it('should return original value if it is not an object', () => { + const test1 = keysToLowercase(['hello']); + const test2 = keysToLowercase('test'); + const test3 = keysToLowercase(1); + const test4 = keysToLowercase(true); + const test5 = keysToLowercase(null); + const test6 = keysToLowercase(undefined); + + expect(test1).toEqual(['hello']); + expect(test2).toEqual('test'); + expect(test3).toEqual(1); + expect(test4).toEqual(true); + expect(test5).toEqual(null); + expect(test6).toEqual(undefined); + }); +}); diff --git a/packages/nodes-base/utils/utilities.ts b/packages/nodes-base/utils/utilities.ts index 28fa916896bf3..8350fdb2bc4bd 100644 --- a/packages/nodes-base/utils/utilities.ts +++ b/packages/nodes-base/utils/utilities.ts @@ -172,3 +172,11 @@ export const fuzzyCompare = (useFuzzyCompare: boolean, compareVersion = 1) => { return isEqual(item1, item2); }; }; + +export const keysToLowercase = (headers: T) => { + if (typeof headers !== 'object' || Array.isArray(headers) || headers === null) return headers; + return Object.entries(headers).reduce((acc, [key, value]) => { + acc[key.toLowerCase()] = value; + return acc; + }, {} as IDataObject); +};