From 837e308acd6a77f4e12fa2758365e3d0b9a2a2ae Mon Sep 17 00:00:00 2001 From: Michael Kret Date: Thu, 11 Apr 2024 15:10:07 +0300 Subject: [PATCH 01/12] :zap: setup --- packages/core/src/NodeExecuteFunctions.ts | 10 +++- .../credentials/HttpSslAuth.credentials.ts | 54 +++++++++++++++++++ .../HttpRequest/V3/HttpRequestV3.node.ts | 23 +++++++- packages/nodes-base/package.json | 1 + packages/workflow/src/Interfaces.ts | 3 ++ 5 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 packages/nodes-base/credentials/HttpSslAuth.credentials.ts diff --git a/packages/core/src/NodeExecuteFunctions.ts b/packages/core/src/NodeExecuteFunctions.ts index 0367d292566db..0061c5855a970 100644 --- a/packages/core/src/NodeExecuteFunctions.ts +++ b/packages/core/src/NodeExecuteFunctions.ts @@ -505,7 +505,15 @@ export async function parseRequestObject(requestObject: IRequestOptions) { agentOptions.rejectUnauthorized = false; agentOptions.secureOptions = crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT; } - axiosConfig.httpsAgent = new Agent(agentOptions); + + if (requestObject.agentOptions) { + axiosConfig.httpsAgent = new Agent({ + ...agentOptions, + ...requestObject.agentOptions, + }); + } else { + axiosConfig.httpsAgent = new Agent(agentOptions); + } axiosConfig.beforeRedirect = getBeforeRedirectFn(agentOptions, axiosConfig); diff --git a/packages/nodes-base/credentials/HttpSslAuth.credentials.ts b/packages/nodes-base/credentials/HttpSslAuth.credentials.ts new file mode 100644 index 0000000000000..1e720094866a7 --- /dev/null +++ b/packages/nodes-base/credentials/HttpSslAuth.credentials.ts @@ -0,0 +1,54 @@ +/* eslint-disable n8n-nodes-base/cred-class-name-unsuffixed */ +/* eslint-disable n8n-nodes-base/cred-class-field-name-unsuffixed */ +import type { ICredentialType, INodeProperties } from 'n8n-workflow'; + +export class HttpSslAuth implements ICredentialType { + name = 'httpSslAuth'; + + displayName = 'SSL Auth'; + + documentationUrl = 'httpRequest'; + + genericAuth = true; + + icon = 'node:n8n-nodes-base.httpRequest'; + + properties: INodeProperties[] = [ + { + displayName: 'CA Certificate', + name: 'ca', + type: 'string', + typeOptions: { + password: true, + }, + default: '', + }, + { + displayName: 'Public Client Certificate', + name: 'cert', + type: 'string', + typeOptions: { + password: true, + }, + default: '', + }, + { + displayName: 'Private Client Key', + name: 'key', + type: 'string', + typeOptions: { + password: true, + }, + default: '', + }, + { + displayName: 'Passphrase', + name: 'passphrase', + type: 'string', + typeOptions: { + password: true, + }, + default: '', + }, + ]; +} diff --git a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts index aadee86b46f34..84877f36d028d 100644 --- a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts +++ b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts @@ -34,7 +34,7 @@ import { replaceNullValues, sanitizeUiMessage, } from '../GenericFunctions'; -import { keysToLowercase } from '@utils/utilities'; +import { formatPrivateKey, keysToLowercase } from '@utils/utilities'; function toText(data: T) { if (typeof data === 'object' && data !== null) { @@ -1218,6 +1218,7 @@ export class HttpRequestV3 implements INodeType { let httpDigestAuth; let httpHeaderAuth; let httpQueryAuth; + let httpSslAuth; let httpCustomAuth; let oAuth1Api; let oAuth2Api; @@ -1275,6 +1276,13 @@ export class HttpRequestV3 implements INodeType { oAuth1Api = await this.getCredentials('oAuth1Api', itemIndex); } else if (genericCredentialType === 'oAuth2Api') { oAuth2Api = await this.getCredentials('oAuth2Api', itemIndex); + } else if (genericCredentialType === 'httpSslAuth') { + httpSslAuth = (await this.getCredentials('httpSslAuth', itemIndex)) as { + ca: string; + cert: string; + key: string; + passphrase: string; + }; } } else if (authentication === 'predefinedCredentialType') { nodeCredentialType = this.getNodeParameter('nodeCredentialType', itemIndex) as string; @@ -1591,6 +1599,19 @@ export class HttpRequestV3 implements INodeType { requestOptions.qs[httpQueryAuth.name as string] = httpQueryAuth.value; authDataKeys.qs = [httpQueryAuth.name as string]; } + if (httpSslAuth !== undefined) { + const agentOptions = { + requestCert: true, + cert: formatPrivateKey(httpSslAuth.cert), + ca: formatPrivateKey(httpSslAuth.ca), + key: formatPrivateKey(httpSslAuth.key), + passphrase: httpSslAuth.passphrase, + }; + + authDataKeys.agentOptions = Object.keys(agentOptions); + + requestOptions.agentOptions = agentOptions; + } if (httpDigestAuth !== undefined) { requestOptions.auth = { user: httpDigestAuth.user as string, diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index 5ea7bbb48d792..8814de4bd29ed 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -168,6 +168,7 @@ "dist/credentials/HttpHeaderAuth.credentials.js", "dist/credentials/HttpCustomAuth.credentials.js", "dist/credentials/HttpQueryAuth.credentials.js", + "dist/credentials/HttpSslAuth.credentials.js", "dist/credentials/HubspotApi.credentials.js", "dist/credentials/HubspotAppToken.credentials.js", "dist/credentials/HubspotDeveloperApi.credentials.js", diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts index 84ccddbd12831..4b86e80987306 100644 --- a/packages/workflow/src/Interfaces.ts +++ b/packages/workflow/src/Interfaces.ts @@ -4,6 +4,7 @@ import type * as express from 'express'; import type FormData from 'form-data'; import type { PathLike } from 'fs'; import type { IncomingHttpHeaders } from 'http'; +import type { SecureContextOptions } from 'tls'; import type { Readable } from 'stream'; import type { URLSearchParams } from 'url'; @@ -547,6 +548,8 @@ export interface IRequestOptions { /** Max number of redirects to follow @default 21 */ maxRedirects?: number; + + agentOptions?: SecureContextOptions; } export interface PaginationOptions { From fe52c1c84d0deff7d7b9076b0f2db155e1535eb6 Mon Sep 17 00:00:00 2001 From: Michael Kret Date: Thu, 11 Apr 2024 16:26:25 +0300 Subject: [PATCH 02/12] :zap: set undefined not empty strings --- .../nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts index 84877f36d028d..f2fecd1df4676 100644 --- a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts +++ b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts @@ -1602,10 +1602,10 @@ export class HttpRequestV3 implements INodeType { if (httpSslAuth !== undefined) { const agentOptions = { requestCert: true, - cert: formatPrivateKey(httpSslAuth.cert), - ca: formatPrivateKey(httpSslAuth.ca), - key: formatPrivateKey(httpSslAuth.key), - passphrase: httpSslAuth.passphrase, + cert: httpSslAuth.cert ? formatPrivateKey(httpSslAuth.cert) : undefined, + ca: httpSslAuth.ca ? formatPrivateKey(httpSslAuth.ca) : undefined, + key: httpSslAuth.key ? formatPrivateKey(httpSslAuth.key) : undefined, + passphrase: httpSslAuth.passphrase || undefined, }; authDataKeys.agentOptions = Object.keys(agentOptions); From 125804c32e578136b336fb182187e96950b21ca0 Mon Sep 17 00:00:00 2001 From: Michael Kret Date: Sat, 13 Apr 2024 09:10:34 +0300 Subject: [PATCH 03/12] :zap: separate option to provide ssl certificates --- .../credentials/HttpSslAuth.credentials.ts | 4 +- .../HttpRequest/V3/HttpRequestV3.node.ts | 80 ++++++++++++++----- 2 files changed, 60 insertions(+), 24 deletions(-) diff --git a/packages/nodes-base/credentials/HttpSslAuth.credentials.ts b/packages/nodes-base/credentials/HttpSslAuth.credentials.ts index 1e720094866a7..e6792e026bdf2 100644 --- a/packages/nodes-base/credentials/HttpSslAuth.credentials.ts +++ b/packages/nodes-base/credentials/HttpSslAuth.credentials.ts @@ -5,12 +5,10 @@ import type { ICredentialType, INodeProperties } from 'n8n-workflow'; export class HttpSslAuth implements ICredentialType { name = 'httpSslAuth'; - displayName = 'SSL Auth'; + displayName = 'SSL Certificates'; documentationUrl = 'httpRequest'; - genericAuth = true; - icon = 'node:n8n-nodes-base.httpRequest'; properties: INodeProperties[] = [ diff --git a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts index f2fecd1df4676..db000b310eff3 100644 --- a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts +++ b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts @@ -56,7 +56,17 @@ export class HttpRequestV3 implements INodeType { }, inputs: ['main'], outputs: ['main'], - credentials: [], + credentials: [ + { + name: 'httpSslAuth', + required: true, + displayOptions: { + show: { + provideSslCertificates: [true], + }, + }, + }, + ], properties: [ { displayName: '', @@ -173,6 +183,23 @@ export class HttpRequestV3 implements INodeType { }, }, }, + { + displayName: 'Provide SSL Certificates', + name: 'provideSslCertificates', + type: 'boolean', + default: false, + }, + { + displayName: 'SSL Certificate', + name: 'sslCertificate', + type: 'credentials', + default: '', + displayOptions: { + show: { + provideSslCertificates: [true], + }, + }, + }, { displayName: 'Send Query Parameters', name: 'sendQuery', @@ -1218,10 +1245,10 @@ export class HttpRequestV3 implements INodeType { let httpDigestAuth; let httpHeaderAuth; let httpQueryAuth; - let httpSslAuth; let httpCustomAuth; let oAuth1Api; let oAuth2Api; + let sslCertificates; let nodeCredentialType: string | undefined; let genericCredentialType: string | undefined; @@ -1276,18 +1303,26 @@ export class HttpRequestV3 implements INodeType { oAuth1Api = await this.getCredentials('oAuth1Api', itemIndex); } else if (genericCredentialType === 'oAuth2Api') { oAuth2Api = await this.getCredentials('oAuth2Api', itemIndex); - } else if (genericCredentialType === 'httpSslAuth') { - httpSslAuth = (await this.getCredentials('httpSslAuth', itemIndex)) as { - ca: string; - cert: string; - key: string; - passphrase: string; - }; } } else if (authentication === 'predefinedCredentialType') { nodeCredentialType = this.getNodeParameter('nodeCredentialType', itemIndex) as string; } + const provideSslCertificates = this.getNodeParameter( + 'provideSslCertificates', + itemIndex, + false, + ); + + if (provideSslCertificates) { + sslCertificates = (await this.getCredentials('httpSslAuth', itemIndex)) as { + ca: string; + cert: string; + key: string; + passphrase: string; + }; + } + const requestMethod = this.getNodeParameter('method', itemIndex) as IHttpRequestMethods; const sendQuery = this.getNodeParameter('sendQuery', itemIndex, false) as boolean; @@ -1599,19 +1634,7 @@ export class HttpRequestV3 implements INodeType { requestOptions.qs[httpQueryAuth.name as string] = httpQueryAuth.value; authDataKeys.qs = [httpQueryAuth.name as string]; } - if (httpSslAuth !== undefined) { - const agentOptions = { - requestCert: true, - cert: httpSslAuth.cert ? formatPrivateKey(httpSslAuth.cert) : undefined, - ca: httpSslAuth.ca ? formatPrivateKey(httpSslAuth.ca) : undefined, - key: httpSslAuth.key ? formatPrivateKey(httpSslAuth.key) : undefined, - passphrase: httpSslAuth.passphrase || undefined, - }; - authDataKeys.agentOptions = Object.keys(agentOptions); - - requestOptions.agentOptions = agentOptions; - } if (httpDigestAuth !== undefined) { requestOptions.auth = { user: httpDigestAuth.user as string, @@ -1639,6 +1662,21 @@ export class HttpRequestV3 implements INodeType { } } + // Add SSL Certificates if provided + if (sslCertificates) { + const agentOptions = { + requestCert: true, + cert: sslCertificates.cert ? formatPrivateKey(sslCertificates.cert) : undefined, + ca: sslCertificates.ca ? formatPrivateKey(sslCertificates.ca) : undefined, + key: sslCertificates.key ? formatPrivateKey(sslCertificates.key) : undefined, + passphrase: sslCertificates.passphrase || undefined, + }; + + authDataKeys.agentOptions = Object.keys(agentOptions); + + requestOptions.agentOptions = agentOptions; + } + if (requestOptions.headers!.accept === undefined) { if (responseFormat === 'json') { requestOptions.headers!.accept = 'application/json,text/*;q=0.99'; From b95fa09db610471cfc9be8d41c4f6c91155badd0 Mon Sep 17 00:00:00 2001 From: Michael Kret Date: Mon, 15 Apr 2024 14:17:05 +0300 Subject: [PATCH 04/12] :zap: ui update --- .../nodes-base/credentials/HttpSslAuth.credentials.ts | 8 +++++--- .../nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts | 1 - 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/nodes-base/credentials/HttpSslAuth.credentials.ts b/packages/nodes-base/credentials/HttpSslAuth.credentials.ts index e6792e026bdf2..06be6d4dd74e5 100644 --- a/packages/nodes-base/credentials/HttpSslAuth.credentials.ts +++ b/packages/nodes-base/credentials/HttpSslAuth.credentials.ts @@ -13,16 +13,17 @@ export class HttpSslAuth implements ICredentialType { properties: INodeProperties[] = [ { - displayName: 'CA Certificate', + displayName: 'CA', name: 'ca', type: 'string', + description: 'Certificate Authority certificate', typeOptions: { password: true, }, default: '', }, { - displayName: 'Public Client Certificate', + displayName: 'Certificate', name: 'cert', type: 'string', typeOptions: { @@ -31,7 +32,7 @@ export class HttpSslAuth implements ICredentialType { default: '', }, { - displayName: 'Private Client Key', + displayName: 'Private Key', name: 'key', type: 'string', typeOptions: { @@ -43,6 +44,7 @@ export class HttpSslAuth implements ICredentialType { displayName: 'Passphrase', name: 'passphrase', type: 'string', + description: 'Optional passphrase for the private key, if the private key is encrypted', typeOptions: { password: true, }, diff --git a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts index db000b310eff3..619c1282fd8c8 100644 --- a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts +++ b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts @@ -1665,7 +1665,6 @@ export class HttpRequestV3 implements INodeType { // Add SSL Certificates if provided if (sslCertificates) { const agentOptions = { - requestCert: true, cert: sslCertificates.cert ? formatPrivateKey(sslCertificates.cert) : undefined, ca: sslCertificates.ca ? formatPrivateKey(sslCertificates.ca) : undefined, key: sslCertificates.key ? formatPrivateKey(sslCertificates.key) : undefined, From 14dbf3d43349d03379a77e88743d3988aa4e1ee1 Mon Sep 17 00:00:00 2001 From: Michael Kret Date: Mon, 15 Apr 2024 14:28:45 +0300 Subject: [PATCH 05/12] :zap: ui update --- packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts index 619c1282fd8c8..c24d142ed1672 100644 --- a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts +++ b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts @@ -184,7 +184,7 @@ export class HttpRequestV3 implements INodeType { }, }, { - displayName: 'Provide SSL Certificates', + displayName: 'SSL Certificates', name: 'provideSslCertificates', type: 'boolean', default: false, From 106b6a689ddd112f7e27bfd7e71e3ab000c194ca Mon Sep 17 00:00:00 2001 From: Michael Kret Date: Tue, 16 Apr 2024 08:49:51 +0300 Subject: [PATCH 06/12] :zap: setAgentOptions utility and tests --- .../nodes/HttpRequest/GenericFunctions.ts | 18 +++++++ .../HttpRequest/V3/HttpRequestV3.node.ts | 34 +++++--------- .../nodes/HttpRequest/interfaces.ts | 6 +++ .../HttpRequest/test/utils/utils.test.ts | 47 ++++++++++++++++++- 4 files changed, 83 insertions(+), 22 deletions(-) create mode 100644 packages/nodes-base/nodes/HttpRequest/interfaces.ts diff --git a/packages/nodes-base/nodes/HttpRequest/GenericFunctions.ts b/packages/nodes-base/nodes/HttpRequest/GenericFunctions.ts index 945277ece5be5..15f61effd7b78 100644 --- a/packages/nodes-base/nodes/HttpRequest/GenericFunctions.ts +++ b/packages/nodes-base/nodes/HttpRequest/GenericFunctions.ts @@ -8,6 +8,8 @@ import type { import set from 'lodash/set'; import FormData from 'form-data'; +import type { HttpSslAuthCredentials } from './interfaces'; +import { formatPrivateKey } from '../../utils/utilities'; export type BodyParameter = { name: string; @@ -194,3 +196,19 @@ export const prepareRequestBody = async ( return await reduceAsync(parameters, defaultReducer); } }; + +export const setAgentOptions = ( + requestOptions: IRequestOptions, + sslCertificates: HttpSslAuthCredentials | undefined, +) => { + if (sslCertificates) { + const agentOptions = { + cert: sslCertificates.cert ? formatPrivateKey(sslCertificates.cert) : undefined, + ca: sslCertificates.ca ? formatPrivateKey(sslCertificates.ca) : undefined, + key: sslCertificates.key ? formatPrivateKey(sslCertificates.key) : undefined, + passphrase: sslCertificates.passphrase || undefined, + }; + + requestOptions.agentOptions = agentOptions; + } +}; diff --git a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts index c24d142ed1672..c50941bbdc872 100644 --- a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts +++ b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts @@ -33,8 +33,10 @@ import { reduceAsync, replaceNullValues, sanitizeUiMessage, + setAgentOptions, } from '../GenericFunctions'; -import { formatPrivateKey, keysToLowercase } from '@utils/utilities'; +import { keysToLowercase } from '@utils/utilities'; +import type { HttpSslAuthCredentials } from '../interfaces'; function toText(data: T) { if (typeof data === 'object' && data !== null) { @@ -1315,12 +1317,10 @@ export class HttpRequestV3 implements INodeType { ); if (provideSslCertificates) { - sslCertificates = (await this.getCredentials('httpSslAuth', itemIndex)) as { - ca: string; - cert: string; - key: string; - passphrase: string; - }; + sslCertificates = (await this.getCredentials( + 'httpSslAuth', + itemIndex, + )) as HttpSslAuthCredentials; } const requestMethod = this.getNodeParameter('method', itemIndex) as IHttpRequestMethods; @@ -1615,6 +1615,12 @@ export class HttpRequestV3 implements INodeType { const authDataKeys: IAuthDataSanitizeKeys = {}; + // Add SSL certificates if any are set + setAgentOptions(requestOptions, sslCertificates); + if (requestOptions.agentOptions) { + authDataKeys.agentOptions = Object.keys(requestOptions.agentOptions); + } + // Add credentials if any are set if (httpBasicAuth !== undefined) { requestOptions.auth = { @@ -1662,20 +1668,6 @@ export class HttpRequestV3 implements INodeType { } } - // Add SSL Certificates if provided - if (sslCertificates) { - const agentOptions = { - cert: sslCertificates.cert ? formatPrivateKey(sslCertificates.cert) : undefined, - ca: sslCertificates.ca ? formatPrivateKey(sslCertificates.ca) : undefined, - key: sslCertificates.key ? formatPrivateKey(sslCertificates.key) : undefined, - passphrase: sslCertificates.passphrase || undefined, - }; - - authDataKeys.agentOptions = Object.keys(agentOptions); - - requestOptions.agentOptions = agentOptions; - } - if (requestOptions.headers!.accept === undefined) { if (responseFormat === 'json') { requestOptions.headers!.accept = 'application/json,text/*;q=0.99'; diff --git a/packages/nodes-base/nodes/HttpRequest/interfaces.ts b/packages/nodes-base/nodes/HttpRequest/interfaces.ts new file mode 100644 index 0000000000000..a5bb4b88a1536 --- /dev/null +++ b/packages/nodes-base/nodes/HttpRequest/interfaces.ts @@ -0,0 +1,6 @@ +export type HttpSslAuthCredentials = { + ca: string; + cert: string; + key: string; + passphrase: string; +}; diff --git a/packages/nodes-base/nodes/HttpRequest/test/utils/utils.test.ts b/packages/nodes-base/nodes/HttpRequest/test/utils/utils.test.ts index 991d0061feaac..21d93ece55dde 100644 --- a/packages/nodes-base/nodes/HttpRequest/test/utils/utils.test.ts +++ b/packages/nodes-base/nodes/HttpRequest/test/utils/utils.test.ts @@ -1,4 +1,5 @@ -import { prepareRequestBody } from '../../GenericFunctions'; +import type { IRequestOptions } from 'n8n-workflow'; +import { prepareRequestBody, setAgentOptions } from '../../GenericFunctions'; import type { BodyParameter, BodyParametersReducer } from '../../GenericFunctions'; describe('HTTP Node Utils, prepareRequestBody', () => { @@ -33,3 +34,47 @@ describe('HTTP Node Utils, prepareRequestBody', () => { expect(result).toEqual({ foo: { bar: { spam: 'baz' } } }); }); }); + +describe('HTTP Node Utils, setAgentOptions', () => { + it("should not have agentOptions as it's undefined", async () => { + const requestOptions: IRequestOptions = { + method: 'GET', + uri: 'https://example.com', + }; + + const sslCertificates = undefined; + + setAgentOptions(requestOptions, sslCertificates); + + expect(requestOptions).toEqual({ + method: 'GET', + uri: 'https://example.com', + }); + }); + it('should have agentOptions set', async () => { + const requestOptions: IRequestOptions = { + method: 'GET', + uri: 'https://example.com', + }; + + const sslCertificates = { + ca: '-----BEGIN CERTIFICATE----- MIIDkzCCAnugAwIBAgIUMSLEzahP0dHVcxwUtMGBKKIrmBQwDQYJKoZIhvcNAQEL BQAwWTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MB4X DTI0MDQxNTExMDYwNFoXDTI0MDUxNTExMDYwNFowWTELMAkGA1UEBhMCQVUxEzAR BgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5 IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEAuTtIHsMtWvqTXKIj4hlMwxBj0RaGomACWxx1QrrMN478kWyWzzAk m725DVDCcKVVxu2FwsfWuReFSHNXfr1zyBNIhqAzKHA5LNBVPJ1r95Ecl0hlT1/5 hhQwKv6VHNsZV1WyVBtZNF/yEQBYkiUAjxC5fLjUc2NptUK7/lwoACCfCyOTFsx3 vmrxGbzewKn9Momoy+n67JErPpM/spf4CggL1dJw1nkZbiIa26OOpyCzj0aL0q+w +3xdoI8OOxaxtE72CqOdvVa+WSZaEE/hnelUwm/oJLdTZOQpGA3tnfziEL7a6bEC f94s2Zn5M1LeafYodVdDfeJqGDaDLJjkRQIDAQABo1MwUTAdBgNVHQ4EFgQUIoo6 igc93d8MNGtKbjT/dfpmNYYwHwYDVR0jBBgwFoAUIoo6igc93d8MNGtKbjT/dfpm NYYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAcu+afpYCp0S7 YaDA6aoMcRY3qqbf56w6XCXIhvrFYR/recuwNPzmp1kIXS0b8CRsd8aDN3YE4o4V +mqCnsjrQB3y/uHOmXNMUD4UKGYsyiwCMDi0611mz/MjhtfZIubml8YJr62hB94b wosQmRBbbtio2e9NS+CHMwJlgVUSu+9TBTwgsSZZ6Temlm/m7jqQTFAmjn+852BX ww2E1kvI4HYRlELSGeWO9bCZvhROhV+ZEH7b1v58Z0RD4gE29tdnBYQKRfRTBMth g5uagkgMAx0TyfARX88zJbvZrg7sabYjE+DA5PKw3ePrnic+f1QmLhcedrsR/UgV a16pVsv+lA== -----END CERTIFICATE-----', + cert: '', + key: '', + passphrase: '', + }; + + setAgentOptions(requestOptions, sslCertificates); + + expect(requestOptions).toStrictEqual({ + method: 'GET', + uri: 'https://example.com', + agentOptions: { + cert: undefined, + ca: '-----BEGIN CERTIFICATE-----\nMIIDkzCCAnugAwIBAgIUMSLEzahP0dHVcxwUtMGBKKIrmBQwDQYJKoZIhvcNAQEL\nBQAwWTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM\nGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MB4X\nDTI0MDQxNTExMDYwNFoXDTI0MDUxNTExMDYwNFowWTELMAkGA1UEBhMCQVUxEzAR\nBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5\nIEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\nMIIBCgKCAQEAuTtIHsMtWvqTXKIj4hlMwxBj0RaGomACWxx1QrrMN478kWyWzzAk\nm725DVDCcKVVxu2FwsfWuReFSHNXfr1zyBNIhqAzKHA5LNBVPJ1r95Ecl0hlT1/5\nhhQwKv6VHNsZV1WyVBtZNF/yEQBYkiUAjxC5fLjUc2NptUK7/lwoACCfCyOTFsx3\nvmrxGbzewKn9Momoy+n67JErPpM/spf4CggL1dJw1nkZbiIa26OOpyCzj0aL0q+w\n+3xdoI8OOxaxtE72CqOdvVa+WSZaEE/hnelUwm/oJLdTZOQpGA3tnfziEL7a6bEC\nf94s2Zn5M1LeafYodVdDfeJqGDaDLJjkRQIDAQABo1MwUTAdBgNVHQ4EFgQUIoo6\nigc93d8MNGtKbjT/dfpmNYYwHwYDVR0jBBgwFoAUIoo6igc93d8MNGtKbjT/dfpm\nNYYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAcu+afpYCp0S7\nYaDA6aoMcRY3qqbf56w6XCXIhvrFYR/recuwNPzmp1kIXS0b8CRsd8aDN3YE4o4V\n+mqCnsjrQB3y/uHOmXNMUD4UKGYsyiwCMDi0611mz/MjhtfZIubml8YJr62hB94b\nwosQmRBbbtio2e9NS+CHMwJlgVUSu+9TBTwgsSZZ6Temlm/m7jqQTFAmjn+852BX\nww2E1kvI4HYRlELSGeWO9bCZvhROhV+ZEH7b1v58Z0RD4gE29tdnBYQKRfRTBMth\ng5uagkgMAx0TyfARX88zJbvZrg7sabYjE+DA5PKw3ePrnic+f1QmLhcedrsR/UgV\na16pVsv+lA==\n-----END CERTIFICATE-----', + key: undefined, + passphrase: undefined, + }, + }); + }); +}); From a3689f8a621eda7f26bad70afbdd5a8b1f471a4e Mon Sep 17 00:00:00 2001 From: Michael Kret Date: Tue, 16 Apr 2024 09:10:57 +0300 Subject: [PATCH 07/12] :zap: parseRequestObject test case --- .../core/test/NodeExecuteFunctions.test.ts | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/packages/core/test/NodeExecuteFunctions.test.ts b/packages/core/test/NodeExecuteFunctions.test.ts index c9d4865b8b220..93b08cdb32a4f 100644 --- a/packages/core/test/NodeExecuteFunctions.test.ts +++ b/packages/core/test/NodeExecuteFunctions.test.ts @@ -387,6 +387,29 @@ describe('NodeExecuteFunctions', () => { expect((axiosOptions.httpsAgent as Agent).options.servername).toEqual('example.de'); }); + test('should set ssl certificates', async () => { + const axiosOptions = await parseRequestObject({ + method: 'GET', + uri: 'https://example.de', + agentOptions: { + cert: undefined, + ca: '-----BEGIN CERTIFICATE-----\nTEST\n-----END CERTIFICATE-----', + key: undefined, + passphrase: undefined, + }, + }); + + expect((axiosOptions.httpsAgent as Agent).options).toEqual({ + servername: 'example.de', + cert: undefined, + ca: '-----BEGIN CERTIFICATE-----\nTEST\n-----END CERTIFICATE-----', + key: undefined, + passphrase: undefined, + noDelay: true, + path: null, + }); + }); + describe('when followRedirect is true', () => { test.each(['GET', 'HEAD'] as IHttpRequestMethods[])( 'should set maxRedirects on %s ', From 17e19cb647f9d5e065c66ee92ea7ffacf668bc03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Thu, 18 Apr 2024 12:03:28 +0200 Subject: [PATCH 08/12] make it work with redirects --- packages/core/src/NodeExecuteFunctions.ts | 11 +---- .../core/test/NodeExecuteFunctions.test.ts | 45 ++++++++++++------- .../nodes/HttpRequest/GenericFunctions.ts | 5 ++- 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/packages/core/src/NodeExecuteFunctions.ts b/packages/core/src/NodeExecuteFunctions.ts index 5e2f94b705a9c..48e20db14bcf9 100644 --- a/packages/core/src/NodeExecuteFunctions.ts +++ b/packages/core/src/NodeExecuteFunctions.ts @@ -497,7 +497,7 @@ export async function parseRequestObject(requestObject: IRequestOptions) { } const host = getHostFromRequestObject(requestObject); - const agentOptions: AgentOptions = {}; + const agentOptions: AgentOptions = { ...requestObject.agentOptions }; if (host) { agentOptions.servername = host; } @@ -506,14 +506,7 @@ export async function parseRequestObject(requestObject: IRequestOptions) { agentOptions.secureOptions = crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT; } - if (requestObject.agentOptions) { - axiosConfig.httpsAgent = new Agent({ - ...agentOptions, - ...requestObject.agentOptions, - }); - } else { - axiosConfig.httpsAgent = new Agent(agentOptions); - } + axiosConfig.httpsAgent = new Agent(agentOptions); axiosConfig.beforeRedirect = getBeforeRedirectFn(agentOptions, axiosConfig); diff --git a/packages/core/test/NodeExecuteFunctions.test.ts b/packages/core/test/NodeExecuteFunctions.test.ts index 93b08cdb32a4f..e4c4efc7c168c 100644 --- a/packages/core/test/NodeExecuteFunctions.test.ts +++ b/packages/core/test/NodeExecuteFunctions.test.ts @@ -1,3 +1,4 @@ +import type { SecureContextOptions } from 'tls'; import { cleanupParameterData, copyInputItems, @@ -387,26 +388,38 @@ describe('NodeExecuteFunctions', () => { expect((axiosOptions.httpsAgent as Agent).options.servername).toEqual('example.de'); }); - test('should set ssl certificates', async () => { - const axiosOptions = await parseRequestObject({ + describe('should set SSL certificates', () => { + const agentOptions: SecureContextOptions = { + ca: '-----BEGIN CERTIFICATE-----\nTEST\n-----END CERTIFICATE-----', + }; + const requestObject: IRequestOptions = { method: 'GET', uri: 'https://example.de', - agentOptions: { - cert: undefined, - ca: '-----BEGIN CERTIFICATE-----\nTEST\n-----END CERTIFICATE-----', - key: undefined, - passphrase: undefined, - }, + agentOptions, + }; + + test('on regular requests', async () => { + const axiosOptions = await parseRequestObject(requestObject); + expect((axiosOptions.httpsAgent as Agent).options).toEqual({ + servername: 'example.de', + ...agentOptions, + noDelay: true, + path: null, + }); }); - expect((axiosOptions.httpsAgent as Agent).options).toEqual({ - servername: 'example.de', - cert: undefined, - ca: '-----BEGIN CERTIFICATE-----\nTEST\n-----END CERTIFICATE-----', - key: undefined, - passphrase: undefined, - noDelay: true, - path: null, + test('on redirected requests', async () => { + const axiosOptions = await parseRequestObject(requestObject); + expect(axiosOptions.beforeRedirect).toBeDefined; + const redirectOptions: Record = { agents: {}, hostname: 'example.de' }; + axiosOptions.beforeRedirect!(redirectOptions, mock()); + expect(redirectOptions.agent).toEqual(redirectOptions.agents.https); + expect((redirectOptions.agent as Agent).options).toEqual({ + servername: 'example.de', + ...agentOptions, + noDelay: true, + path: null, + }); }); }); diff --git a/packages/nodes-base/nodes/HttpRequest/GenericFunctions.ts b/packages/nodes-base/nodes/HttpRequest/GenericFunctions.ts index 15f61effd7b78..778f03764c4ce 100644 --- a/packages/nodes-base/nodes/HttpRequest/GenericFunctions.ts +++ b/packages/nodes-base/nodes/HttpRequest/GenericFunctions.ts @@ -1,3 +1,4 @@ +import type { SecureContextOptions } from 'tls'; import type { IDataObject, INodeExecutionData, @@ -202,13 +203,13 @@ export const setAgentOptions = ( sslCertificates: HttpSslAuthCredentials | undefined, ) => { if (sslCertificates) { - const agentOptions = { + const agentOptions: SecureContextOptions = { cert: sslCertificates.cert ? formatPrivateKey(sslCertificates.cert) : undefined, ca: sslCertificates.ca ? formatPrivateKey(sslCertificates.ca) : undefined, key: sslCertificates.key ? formatPrivateKey(sslCertificates.key) : undefined, passphrase: sslCertificates.passphrase || undefined, }; - requestOptions.agentOptions = agentOptions; + requestOptions.agentOptions = { ...agentOptions }; } }; From 20245dcde2b210dbe535ff3c8820c5f1e21fca58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Thu, 18 Apr 2024 12:11:01 +0200 Subject: [PATCH 09/12] don't use actual certs in tests. they trigger secret-scanning tools --- .../nodes/HttpRequest/GenericFunctions.ts | 15 +++++++-------- .../nodes-base/nodes/HttpRequest/interfaces.ts | 8 ++++---- .../nodes/HttpRequest/test/utils/utils.test.ts | 11 +++-------- 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/packages/nodes-base/nodes/HttpRequest/GenericFunctions.ts b/packages/nodes-base/nodes/HttpRequest/GenericFunctions.ts index 778f03764c4ce..54a37a595330b 100644 --- a/packages/nodes-base/nodes/HttpRequest/GenericFunctions.ts +++ b/packages/nodes-base/nodes/HttpRequest/GenericFunctions.ts @@ -203,13 +203,12 @@ export const setAgentOptions = ( sslCertificates: HttpSslAuthCredentials | undefined, ) => { if (sslCertificates) { - const agentOptions: SecureContextOptions = { - cert: sslCertificates.cert ? formatPrivateKey(sslCertificates.cert) : undefined, - ca: sslCertificates.ca ? formatPrivateKey(sslCertificates.ca) : undefined, - key: sslCertificates.key ? formatPrivateKey(sslCertificates.key) : undefined, - passphrase: sslCertificates.passphrase || undefined, - }; - - requestOptions.agentOptions = { ...agentOptions }; + const agentOptions: SecureContextOptions = {}; + if (sslCertificates.ca) agentOptions.ca = formatPrivateKey(sslCertificates.ca); + if (sslCertificates.cert) agentOptions.cert = formatPrivateKey(sslCertificates.cert); + if (sslCertificates.key) agentOptions.key = formatPrivateKey(sslCertificates.key); + if (sslCertificates.passphrase) + agentOptions.passphrase = formatPrivateKey(sslCertificates.passphrase); + requestOptions.agentOptions = agentOptions; } }; diff --git a/packages/nodes-base/nodes/HttpRequest/interfaces.ts b/packages/nodes-base/nodes/HttpRequest/interfaces.ts index a5bb4b88a1536..83ef3532daa2e 100644 --- a/packages/nodes-base/nodes/HttpRequest/interfaces.ts +++ b/packages/nodes-base/nodes/HttpRequest/interfaces.ts @@ -1,6 +1,6 @@ export type HttpSslAuthCredentials = { - ca: string; - cert: string; - key: string; - passphrase: string; + ca?: string; + cert?: string; + key?: string; + passphrase?: string; }; diff --git a/packages/nodes-base/nodes/HttpRequest/test/utils/utils.test.ts b/packages/nodes-base/nodes/HttpRequest/test/utils/utils.test.ts index 21d93ece55dde..716b59e9b800f 100644 --- a/packages/nodes-base/nodes/HttpRequest/test/utils/utils.test.ts +++ b/packages/nodes-base/nodes/HttpRequest/test/utils/utils.test.ts @@ -51,6 +51,7 @@ describe('HTTP Node Utils, setAgentOptions', () => { uri: 'https://example.com', }); }); + it('should have agentOptions set', async () => { const requestOptions: IRequestOptions = { method: 'GET', @@ -58,10 +59,7 @@ describe('HTTP Node Utils, setAgentOptions', () => { }; const sslCertificates = { - ca: '-----BEGIN CERTIFICATE----- MIIDkzCCAnugAwIBAgIUMSLEzahP0dHVcxwUtMGBKKIrmBQwDQYJKoZIhvcNAQEL BQAwWTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MB4X DTI0MDQxNTExMDYwNFoXDTI0MDUxNTExMDYwNFowWTELMAkGA1UEBhMCQVUxEzAR BgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5 IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEAuTtIHsMtWvqTXKIj4hlMwxBj0RaGomACWxx1QrrMN478kWyWzzAk m725DVDCcKVVxu2FwsfWuReFSHNXfr1zyBNIhqAzKHA5LNBVPJ1r95Ecl0hlT1/5 hhQwKv6VHNsZV1WyVBtZNF/yEQBYkiUAjxC5fLjUc2NptUK7/lwoACCfCyOTFsx3 vmrxGbzewKn9Momoy+n67JErPpM/spf4CggL1dJw1nkZbiIa26OOpyCzj0aL0q+w +3xdoI8OOxaxtE72CqOdvVa+WSZaEE/hnelUwm/oJLdTZOQpGA3tnfziEL7a6bEC f94s2Zn5M1LeafYodVdDfeJqGDaDLJjkRQIDAQABo1MwUTAdBgNVHQ4EFgQUIoo6 igc93d8MNGtKbjT/dfpmNYYwHwYDVR0jBBgwFoAUIoo6igc93d8MNGtKbjT/dfpm NYYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAcu+afpYCp0S7 YaDA6aoMcRY3qqbf56w6XCXIhvrFYR/recuwNPzmp1kIXS0b8CRsd8aDN3YE4o4V +mqCnsjrQB3y/uHOmXNMUD4UKGYsyiwCMDi0611mz/MjhtfZIubml8YJr62hB94b wosQmRBbbtio2e9NS+CHMwJlgVUSu+9TBTwgsSZZ6Temlm/m7jqQTFAmjn+852BX ww2E1kvI4HYRlELSGeWO9bCZvhROhV+ZEH7b1v58Z0RD4gE29tdnBYQKRfRTBMth g5uagkgMAx0TyfARX88zJbvZrg7sabYjE+DA5PKw3ePrnic+f1QmLhcedrsR/UgV a16pVsv+lA== -----END CERTIFICATE-----', - cert: '', - key: '', - passphrase: '', + ca: 'mock-ca', }; setAgentOptions(requestOptions, sslCertificates); @@ -70,10 +68,7 @@ describe('HTTP Node Utils, setAgentOptions', () => { method: 'GET', uri: 'https://example.com', agentOptions: { - cert: undefined, - ca: '-----BEGIN CERTIFICATE-----\nMIIDkzCCAnugAwIBAgIUMSLEzahP0dHVcxwUtMGBKKIrmBQwDQYJKoZIhvcNAQEL\nBQAwWTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM\nGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MB4X\nDTI0MDQxNTExMDYwNFoXDTI0MDUxNTExMDYwNFowWTELMAkGA1UEBhMCQVUxEzAR\nBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5\nIEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\nMIIBCgKCAQEAuTtIHsMtWvqTXKIj4hlMwxBj0RaGomACWxx1QrrMN478kWyWzzAk\nm725DVDCcKVVxu2FwsfWuReFSHNXfr1zyBNIhqAzKHA5LNBVPJ1r95Ecl0hlT1/5\nhhQwKv6VHNsZV1WyVBtZNF/yEQBYkiUAjxC5fLjUc2NptUK7/lwoACCfCyOTFsx3\nvmrxGbzewKn9Momoy+n67JErPpM/spf4CggL1dJw1nkZbiIa26OOpyCzj0aL0q+w\n+3xdoI8OOxaxtE72CqOdvVa+WSZaEE/hnelUwm/oJLdTZOQpGA3tnfziEL7a6bEC\nf94s2Zn5M1LeafYodVdDfeJqGDaDLJjkRQIDAQABo1MwUTAdBgNVHQ4EFgQUIoo6\nigc93d8MNGtKbjT/dfpmNYYwHwYDVR0jBBgwFoAUIoo6igc93d8MNGtKbjT/dfpm\nNYYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAcu+afpYCp0S7\nYaDA6aoMcRY3qqbf56w6XCXIhvrFYR/recuwNPzmp1kIXS0b8CRsd8aDN3YE4o4V\n+mqCnsjrQB3y/uHOmXNMUD4UKGYsyiwCMDi0611mz/MjhtfZIubml8YJr62hB94b\nwosQmRBbbtio2e9NS+CHMwJlgVUSu+9TBTwgsSZZ6Temlm/m7jqQTFAmjn+852BX\nww2E1kvI4HYRlELSGeWO9bCZvhROhV+ZEH7b1v58Z0RD4gE29tdnBYQKRfRTBMth\ng5uagkgMAx0TyfARX88zJbvZrg7sabYjE+DA5PKw3ePrnic+f1QmLhcedrsR/UgV\na16pVsv+lA==\n-----END CERTIFICATE-----', - key: undefined, - passphrase: undefined, + ca: 'mock-ca', }, }); }); From cbba2a8a731bbfb0a6410870a626cc32834578c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Thu, 18 Apr 2024 12:17:32 +0200 Subject: [PATCH 10/12] lintfix --- packages/core/test/NodeExecuteFunctions.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core/test/NodeExecuteFunctions.test.ts b/packages/core/test/NodeExecuteFunctions.test.ts index e4c4efc7c168c..9300a5d9db517 100644 --- a/packages/core/test/NodeExecuteFunctions.test.ts +++ b/packages/core/test/NodeExecuteFunctions.test.ts @@ -411,6 +411,7 @@ describe('NodeExecuteFunctions', () => { test('on redirected requests', async () => { const axiosOptions = await parseRequestObject(requestObject); expect(axiosOptions.beforeRedirect).toBeDefined; + // eslint-disable-next-line @typescript-eslint/no-explicit-any const redirectOptions: Record = { agents: {}, hostname: 'example.de' }; axiosOptions.beforeRedirect!(redirectOptions, mock()); expect(redirectOptions.agent).toEqual(redirectOptions.agents.https); From 96a0ff4aeff00767db500b9e2b7d7b98797e33d2 Mon Sep 17 00:00:00 2001 From: Michael Kret Date: Wed, 24 Apr 2024 15:49:58 +0300 Subject: [PATCH 11/12] :zap: moved toggle into node settings --- .../nodes/HttpRequest/V3/HttpRequestV3.node.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts index 9c0d3a5cf088b..b0f36449718d9 100644 --- a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts +++ b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts @@ -190,6 +190,19 @@ export class HttpRequestV3 implements INodeType { name: 'provideSslCertificates', type: 'boolean', default: false, + isNodeSetting: true, + }, + { + displayName: "Provide certificates in node's 'Credential for SSL Certificates' parameter", + name: 'provideSslCertificates', + type: 'notice', + default: '', + isNodeSetting: true, + displayOptions: { + show: { + provideSslCertificates: [true], + }, + }, }, { displayName: 'SSL Certificate', From b192fdccf42d26bb226b85bd2c8fad6a054afc0f Mon Sep 17 00:00:00 2001 From: Michael Kret Date: Wed, 24 Apr 2024 16:03:47 +0300 Subject: [PATCH 12/12] :zap: notice parameter renamed --- packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts index b0f36449718d9..386721c3b1025 100644 --- a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts +++ b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts @@ -194,7 +194,7 @@ export class HttpRequestV3 implements INodeType { }, { displayName: "Provide certificates in node's 'Credential for SSL Certificates' parameter", - name: 'provideSslCertificates', + name: 'provideSslCertificatesNotice', type: 'notice', default: '', isNodeSetting: true,