mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-18 02:21:13 +00:00
refactor(core)!: Make getBinaryStream async (#7247)
Story: [PAY-846](https://linear.app/n8n/issue/PAY-846) | Related: https://github.com/n8n-io/n8n/pull/7225 For the S3 backend for external storage of binary data and execution data, the `getAsStream` method in the binary data manager interface used by FS and S3 will need to become async. This is a breaking change for nodes-base.
This commit is contained in:
@@ -138,21 +138,31 @@ export const binaryContentTypes = [
|
||||
export type BodyParametersReducer = (
|
||||
acc: IDataObject,
|
||||
cur: { name: string; value: string },
|
||||
) => IDataObject;
|
||||
) => Promise<IDataObject>;
|
||||
|
||||
export const prepareRequestBody = (
|
||||
export async function reduceAsync<T, R>(
|
||||
arr: T[],
|
||||
reducer: (acc: Awaited<Promise<R>>, cur: T) => Promise<R>,
|
||||
init: Promise<R> = Promise.resolve({} as R),
|
||||
): Promise<R> {
|
||||
return arr.reduce(async (promiseAcc, item) => {
|
||||
return reducer(await promiseAcc, item);
|
||||
}, init);
|
||||
}
|
||||
|
||||
export const prepareRequestBody = async (
|
||||
parameters: BodyParameter[],
|
||||
bodyType: string,
|
||||
version: number,
|
||||
defaultReducer: BodyParametersReducer,
|
||||
) => {
|
||||
if (bodyType === 'json' && version >= 4) {
|
||||
return parameters.reduce((acc, entry) => {
|
||||
const value = entry.value;
|
||||
set(acc, entry.name, value);
|
||||
return acc;
|
||||
}, {} as IDataObject);
|
||||
return parameters.reduce(async (acc, entry) => {
|
||||
const result = await acc;
|
||||
set(result, entry.name, entry.value);
|
||||
return result;
|
||||
}, Promise.resolve({}));
|
||||
} else {
|
||||
return parameters.reduce(defaultReducer, {});
|
||||
return reduceAsync(parameters, defaultReducer);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -31,6 +31,7 @@ import {
|
||||
binaryContentTypes,
|
||||
getOAuth2AdditionalParameters,
|
||||
prepareRequestBody,
|
||||
reduceAsync,
|
||||
replaceNullValues,
|
||||
sanitizeUiMessage,
|
||||
} from '../GenericFunctions';
|
||||
@@ -1161,7 +1162,7 @@ export class HttpRequestV3 implements INodeType {
|
||||
});
|
||||
}
|
||||
|
||||
const parametersToKeyValue = (
|
||||
const parametersToKeyValue = async (
|
||||
accumulator: { [key: string]: any },
|
||||
cur: { name: string; value: string; parameterType?: string; inputDataFieldName?: string },
|
||||
) => {
|
||||
@@ -1171,7 +1172,7 @@ export class HttpRequestV3 implements INodeType {
|
||||
let uploadData: Buffer | Readable;
|
||||
const itemBinaryData = items[itemIndex].binary![cur.inputDataFieldName];
|
||||
if (itemBinaryData.id) {
|
||||
uploadData = this.helpers.getBinaryStream(itemBinaryData.id);
|
||||
uploadData = await this.helpers.getBinaryStream(itemBinaryData.id);
|
||||
} else {
|
||||
uploadData = Buffer.from(itemBinaryData.data, BINARY_ENCODING);
|
||||
}
|
||||
@@ -1192,7 +1193,7 @@ export class HttpRequestV3 implements INodeType {
|
||||
// Get parameters defined in the UI
|
||||
if (sendBody && bodyParameters) {
|
||||
if (specifyBody === 'keypair' || bodyContentType === 'multipart-form-data') {
|
||||
requestOptions.body = prepareRequestBody(
|
||||
requestOptions.body = await prepareRequestBody(
|
||||
bodyParameters,
|
||||
bodyContentType,
|
||||
nodeVersion,
|
||||
@@ -1243,7 +1244,7 @@ export class HttpRequestV3 implements INodeType {
|
||||
const itemBinaryData = this.helpers.assertBinaryData(itemIndex, inputDataFieldName);
|
||||
|
||||
if (itemBinaryData.id) {
|
||||
uploadData = this.helpers.getBinaryStream(itemBinaryData.id);
|
||||
uploadData = await this.helpers.getBinaryStream(itemBinaryData.id);
|
||||
const metadata = await this.helpers.getBinaryMetadata(itemBinaryData.id);
|
||||
contentLength = metadata.fileSize;
|
||||
} else {
|
||||
@@ -1264,7 +1265,7 @@ export class HttpRequestV3 implements INodeType {
|
||||
// Get parameters defined in the UI
|
||||
if (sendQuery && queryParameters) {
|
||||
if (specifyQuery === 'keypair') {
|
||||
requestOptions.qs = queryParameters.reduce(parametersToKeyValue, {});
|
||||
requestOptions.qs = await reduceAsync(queryParameters, parametersToKeyValue);
|
||||
} else if (specifyQuery === 'json') {
|
||||
// query is specified using JSON
|
||||
try {
|
||||
@@ -1287,7 +1288,7 @@ export class HttpRequestV3 implements INodeType {
|
||||
if (sendHeaders && headerParameters) {
|
||||
let additionalHeaders: IDataObject = {};
|
||||
if (specifyHeaders === 'keypair') {
|
||||
additionalHeaders = headerParameters.reduce(parametersToKeyValue, {});
|
||||
additionalHeaders = await reduceAsync(headerParameters, parametersToKeyValue);
|
||||
} else if (specifyHeaders === 'json') {
|
||||
// body is specified using JSON
|
||||
try {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { prepareRequestBody } from '../../GenericFunctions';
|
||||
import type { BodyParameter, BodyParametersReducer } from '../../GenericFunctions';
|
||||
|
||||
describe('HTTP Node Utils, prepareRequestBody', () => {
|
||||
it('should call default reducer', () => {
|
||||
it('should call default reducer', async () => {
|
||||
const bodyParameters: BodyParameter[] = [
|
||||
{
|
||||
name: 'foo.bar',
|
||||
@@ -11,15 +11,13 @@ describe('HTTP Node Utils, prepareRequestBody', () => {
|
||||
];
|
||||
const defaultReducer: BodyParametersReducer = jest.fn();
|
||||
|
||||
prepareRequestBody(bodyParameters, 'json', 3, defaultReducer);
|
||||
await prepareRequestBody(bodyParameters, 'json', 3, defaultReducer);
|
||||
|
||||
expect(defaultReducer).toBeCalledTimes(1);
|
||||
expect(defaultReducer).toBeCalledWith({}, { name: 'foo.bar', value: 'baz' }, 0, [
|
||||
{ name: 'foo.bar', value: 'baz' },
|
||||
]);
|
||||
expect(defaultReducer).toBeCalledWith({}, { name: 'foo.bar', value: 'baz' });
|
||||
});
|
||||
|
||||
it('should call process dot notations', () => {
|
||||
it('should call process dot notations', async () => {
|
||||
const bodyParameters: BodyParameter[] = [
|
||||
{
|
||||
name: 'foo.bar.spam',
|
||||
@@ -28,7 +26,7 @@ describe('HTTP Node Utils, prepareRequestBody', () => {
|
||||
];
|
||||
const defaultReducer: BodyParametersReducer = jest.fn();
|
||||
|
||||
const result = prepareRequestBody(bodyParameters, 'json', 4, defaultReducer);
|
||||
const result = await prepareRequestBody(bodyParameters, 'json', 4, defaultReducer);
|
||||
|
||||
expect(defaultReducer).toBeCalledTimes(0);
|
||||
expect(result).toBeDefined();
|
||||
|
||||
Reference in New Issue
Block a user