mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-21 11:49:59 +00:00
fix(core): Use hostname from URL instead of Host header for SNI (#8562)
This commit is contained in:
@@ -31,7 +31,7 @@ import FormData from 'form-data';
|
|||||||
import { createReadStream } from 'fs';
|
import { createReadStream } from 'fs';
|
||||||
import { access as fsAccess, writeFile as fsWriteFile } from 'fs/promises';
|
import { access as fsAccess, writeFile as fsWriteFile } from 'fs/promises';
|
||||||
import { IncomingMessage, type IncomingHttpHeaders } from 'http';
|
import { IncomingMessage, type IncomingHttpHeaders } from 'http';
|
||||||
import { Agent } from 'https';
|
import { Agent, type AgentOptions } from 'https';
|
||||||
import get from 'lodash/get';
|
import get from 'lodash/get';
|
||||||
import pick from 'lodash/pick';
|
import pick from 'lodash/pick';
|
||||||
import { extension, lookup } from 'mime-types';
|
import { extension, lookup } from 'mime-types';
|
||||||
@@ -229,7 +229,22 @@ async function generateContentLengthHeader(config: AxiosRequestConfig) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function parseRequestObject(requestObject: IDataObject) {
|
const getHostFromRequestObject = (
|
||||||
|
requestObject: Partial<{
|
||||||
|
url: string;
|
||||||
|
uri: string;
|
||||||
|
baseURL: string;
|
||||||
|
}>,
|
||||||
|
): string | null => {
|
||||||
|
try {
|
||||||
|
const url = (requestObject.url ?? requestObject.uri) as string;
|
||||||
|
return new URL(url, requestObject.baseURL).hostname;
|
||||||
|
} catch (error) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function parseRequestObject(requestObject: IDataObject) {
|
||||||
// This function is a temporary implementation
|
// This function is a temporary implementation
|
||||||
// That translates all http requests done via
|
// That translates all http requests done via
|
||||||
// the request library to axios directly
|
// the request library to axios directly
|
||||||
@@ -468,6 +483,17 @@ async function parseRequestObject(requestObject: IDataObject) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const host = getHostFromRequestObject(requestObject);
|
||||||
|
const agentOptions: AgentOptions = {};
|
||||||
|
if (host) {
|
||||||
|
agentOptions.servername = host;
|
||||||
|
}
|
||||||
|
if (requestObject.rejectUnauthorized === false) {
|
||||||
|
agentOptions.rejectUnauthorized = false;
|
||||||
|
agentOptions.secureOptions = crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT;
|
||||||
|
}
|
||||||
|
axiosConfig.httpsAgent = new Agent(agentOptions);
|
||||||
|
|
||||||
if (requestObject.timeout !== undefined) {
|
if (requestObject.timeout !== undefined) {
|
||||||
axiosConfig.timeout = requestObject.timeout as number;
|
axiosConfig.timeout = requestObject.timeout as number;
|
||||||
}
|
}
|
||||||
@@ -732,14 +758,11 @@ export async function proxyRequestToAxios(
|
|||||||
maxBodyLength: Infinity,
|
maxBodyLength: Infinity,
|
||||||
maxContentLength: Infinity,
|
maxContentLength: Infinity,
|
||||||
};
|
};
|
||||||
let configObject: ConfigObject;
|
let configObject: ConfigObject & { uri?: string };
|
||||||
if (uriOrObject !== undefined && typeof uriOrObject === 'string') {
|
if (typeof uriOrObject === 'string') {
|
||||||
axiosConfig.url = uriOrObject;
|
configObject = { uri: uriOrObject, ...options };
|
||||||
}
|
|
||||||
if (uriOrObject !== undefined && typeof uriOrObject === 'object') {
|
|
||||||
configObject = uriOrObject;
|
|
||||||
} else {
|
} else {
|
||||||
configObject = options || {};
|
configObject = uriOrObject ?? {};
|
||||||
}
|
}
|
||||||
|
|
||||||
axiosConfig = Object.assign(axiosConfig, await parseRequestObject(configObject));
|
axiosConfig = Object.assign(axiosConfig, await parseRequestObject(configObject));
|
||||||
@@ -859,11 +882,15 @@ function convertN8nRequestToAxios(n8nRequest: IHttpRequestOptions): AxiosRequest
|
|||||||
axiosRequest.responseType = n8nRequest.encoding;
|
axiosRequest.responseType = n8nRequest.encoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n8nRequest.skipSslCertificateValidation === true) {
|
const host = getHostFromRequestObject(n8nRequest);
|
||||||
axiosRequest.httpsAgent = new Agent({
|
const agentOptions: AgentOptions = {};
|
||||||
rejectUnauthorized: false,
|
if (host) {
|
||||||
});
|
agentOptions.servername = host;
|
||||||
}
|
}
|
||||||
|
if (n8nRequest.skipSslCertificateValidation === true) {
|
||||||
|
agentOptions.rejectUnauthorized = false;
|
||||||
|
}
|
||||||
|
axiosRequest.httpsAgent = new Agent(agentOptions);
|
||||||
|
|
||||||
if (n8nRequest.arrayFormat !== undefined) {
|
if (n8nRequest.arrayFormat !== undefined) {
|
||||||
axiosRequest.paramsSerializer = (params) => {
|
axiosRequest.paramsSerializer = (params) => {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import {
|
|||||||
copyInputItems,
|
copyInputItems,
|
||||||
getBinaryDataBuffer,
|
getBinaryDataBuffer,
|
||||||
parseIncomingMessage,
|
parseIncomingMessage,
|
||||||
|
parseRequestObject,
|
||||||
proxyRequestToAxios,
|
proxyRequestToAxios,
|
||||||
setBinaryDataBuffer,
|
setBinaryDataBuffer,
|
||||||
} from '@/NodeExecuteFunctions';
|
} from '@/NodeExecuteFunctions';
|
||||||
@@ -21,6 +22,7 @@ import nock from 'nock';
|
|||||||
import { tmpdir } from 'os';
|
import { tmpdir } from 'os';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import Container from 'typedi';
|
import Container from 'typedi';
|
||||||
|
import type { Agent } from 'https';
|
||||||
|
|
||||||
const temporaryDir = mkdtempSync(join(tmpdir(), 'n8n'));
|
const temporaryDir = mkdtempSync(join(tmpdir(), 'n8n'));
|
||||||
|
|
||||||
@@ -358,6 +360,16 @@ describe('NodeExecuteFunctions', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('parseRequestObject', () => {
|
||||||
|
test('should not use Host header for SNI', async () => {
|
||||||
|
const axiosOptions = await parseRequestObject({
|
||||||
|
url: 'https://example.de/foo/bar',
|
||||||
|
headers: { Host: 'other.host.com' },
|
||||||
|
});
|
||||||
|
expect((axiosOptions.httpsAgent as Agent).options.servername).toEqual('example.de');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('copyInputItems', () => {
|
describe('copyInputItems', () => {
|
||||||
it('should pick only selected properties', () => {
|
it('should pick only selected properties', () => {
|
||||||
const output = copyInputItems(
|
const output = copyInputItems(
|
||||||
|
|||||||
Reference in New Issue
Block a user