diff --git a/packages/cli/src/WebhookHelpers.ts b/packages/cli/src/WebhookHelpers.ts index e399f10beb..4ac4dbd1fa 100644 --- a/packages/cli/src/WebhookHelpers.ts +++ b/packages/cli/src/WebhookHelpers.ts @@ -15,10 +15,13 @@ /* eslint-disable prefer-destructuring */ import type express from 'express'; import get from 'lodash.get'; +import stream from 'stream'; +import { promisify } from 'util'; import { BinaryDataManager, NodeExecuteFunctions, eventEmitter } from 'n8n-core'; import type { + IBinaryData, IBinaryKeyData, IDataObject, IDeferredPromise, @@ -59,6 +62,8 @@ import type { WorkflowEntity } from '@db/entities/WorkflowEntity'; import { getWorkflowOwner } from '@/UserManagement/UserManagementHelper'; import { Container } from 'typedi'; +const pipeline = promisify(stream.pipeline); + export const WEBHOOK_METHODS = ['DELETE', 'GET', 'HEAD', 'PATCH', 'POST', 'PUT']; /** @@ -418,13 +423,17 @@ export async function executeWebhook( return; } - if (Buffer.isBuffer(response.body)) { + const binaryData = (response.body as IDataObject)?.binaryData as IBinaryData; + if (binaryData?.id) { + res.header(response.headers); + const stream = NodeExecuteFunctions.getBinaryStream(binaryData.id); + void pipeline(stream, res).then(() => + responseCallback(null, { noWebhookResponse: true }), + ); + } else if (Buffer.isBuffer(response.body)) { res.header(response.headers); res.end(response.body); - - responseCallback(null, { - noWebhookResponse: true, - }); + responseCallback(null, { noWebhookResponse: true }); } else { // TODO: This probably needs some more changes depending on the options on the // Webhook Response node diff --git a/packages/nodes-base/nodes/RespondToWebhook/RespondToWebhook.node.ts b/packages/nodes-base/nodes/RespondToWebhook/RespondToWebhook.node.ts index 3296d404c8..699dd40a52 100644 --- a/packages/nodes-base/nodes/RespondToWebhook/RespondToWebhook.node.ts +++ b/packages/nodes-base/nodes/RespondToWebhook/RespondToWebhook.node.ts @@ -1,3 +1,4 @@ +import type { Readable } from 'stream'; import type { IDataObject, IExecuteFunctions, @@ -7,7 +8,7 @@ import type { INodeType, INodeTypeDescription, } from 'n8n-workflow'; -import { jsonParse, NodeOperationError } from 'n8n-workflow'; +import { jsonParse, BINARY_ENCODING, NodeOperationError } from 'n8n-workflow'; export class RespondToWebhook implements INodeType { description: INodeTypeDescription = { @@ -201,7 +202,7 @@ export class RespondToWebhook implements INodeType { } } - let responseBody: IN8nHttpResponse; + let responseBody: IN8nHttpResponse | Readable; if (respondWith === 'json') { const responseBodyParameter = this.getNodeParameter('responseBody', 0) as string; if (responseBodyParameter) { @@ -235,15 +236,16 @@ export class RespondToWebhook implements INodeType { } const binaryData = this.helpers.assertBinaryData(0, responseBinaryPropertyName); - const binaryDataBuffer = await this.helpers.getBinaryDataBuffer( - 0, - responseBinaryPropertyName, - ); + if (binaryData.id) { + responseBody = { binaryData }; + } else { + responseBody = Buffer.from(binaryData.data, BINARY_ENCODING); + headers['content-length'] = (responseBody as Buffer).length; + } if (!headers['content-type']) { headers['content-type'] = binaryData.mimeType; } - responseBody = binaryDataBuffer; } else if (respondWith !== 'noData') { throw new NodeOperationError( this.getNode(), diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts index b343a9b267..60a3555546 100644 --- a/packages/workflow/src/Interfaces.ts +++ b/packages/workflow/src/Interfaces.ts @@ -527,7 +527,7 @@ export interface IHttpRequestOptions { export type IN8nHttpResponse = IDataObject | Buffer | GenericValue | GenericValue[] | null; export interface IN8nHttpFullResponse { - body: IN8nHttpResponse; + body: IN8nHttpResponse | Readable; headers: IDataObject; statusCode: number; statusMessage?: string;