diff --git a/packages/nodes-base/nodes/RespondToWebhook/RespondToWebhook.node.ts b/packages/nodes-base/nodes/RespondToWebhook/RespondToWebhook.node.ts index 586f9de005..d6da0a0c51 100644 --- a/packages/nodes-base/nodes/RespondToWebhook/RespondToWebhook.node.ts +++ b/packages/nodes-base/nodes/RespondToWebhook/RespondToWebhook.node.ts @@ -9,6 +9,7 @@ import type { INodeTypeDescription, } from 'n8n-workflow'; import { jsonParse, BINARY_ENCODING, NodeOperationError } from 'n8n-workflow'; +import set from 'lodash/set'; export class RespondToWebhook implements INodeType { description: INodeTypeDescription = { @@ -25,34 +26,52 @@ export class RespondToWebhook implements INodeType { outputs: ['main'], credentials: [], properties: [ + { + displayName: + 'Verify that the "Webhook" node\'s "Respond" parameter is set to "Using Respond to Webhook Node". More details', + name: 'generalNotice', + type: 'notice', + default: '', + }, { displayName: 'Respond With', name: 'respondWith', type: 'options', options: [ { - name: 'Binary', + name: 'All Incoming Items', + value: 'allIncomingItems', + description: 'Respond with all input JSON items', + }, + { + name: 'Binary File', value: 'binary', + description: 'Respond with incoming file binary data', }, { name: 'First Incoming Item', value: 'firstIncomingItem', + description: 'Respond with the first input JSON item', }, { name: 'JSON', value: 'json', + description: 'Respond with a custom JSON body', }, { name: 'No Data', value: 'noData', + description: 'Respond with an empty body', }, { name: 'Redirect', value: 'redirect', + description: 'Respond with a redirect to a given URL', }, { name: 'Text', value: 'text', + description: 'Respond with a simple text message body', }, ], default: 'firstIncomingItem', @@ -60,7 +79,7 @@ export class RespondToWebhook implements INodeType { }, { displayName: - 'When using expressions, note that this node will only run for the first item in the input data.', + 'When using expressions, note that this node will only run for the first item in the input data', name: 'webhookNotice', type: 'notice', displayOptions: { @@ -94,9 +113,13 @@ export class RespondToWebhook implements INodeType { respondWith: ['json'], }, }, - default: '', - placeholder: '{ "key": "value" }', - description: 'The HTTP Response JSON data', + default: '{\n "myField": "value"\n}', + typeOptions: { + editor: 'json', + editorLanguage: 'json', + rows: 4, + }, + description: 'The HTTP response JSON data', }, { displayName: 'Response Body', @@ -107,9 +130,12 @@ export class RespondToWebhook implements INodeType { respondWith: ['text'], }, }, + typeOptions: { + rows: 2, + }, default: '', - placeholder: 'e.g. Workflow started', - description: 'The HTTP Response text data', + placeholder: 'e.g. Workflow completed', + description: 'The HTTP response text data', }, { displayName: 'Response Data Source', @@ -165,7 +191,7 @@ export class RespondToWebhook implements INodeType { maxValue: 599, }, default: 200, - description: 'The HTTP Response code to return. Defaults to 200.', + description: 'The HTTP response code to return. Defaults to 200.', }, { displayName: 'Response Headers', @@ -200,6 +226,19 @@ export class RespondToWebhook implements INodeType { }, ], }, + { + displayName: 'Put Response in Field', + name: 'responseKey', + type: 'string', + displayOptions: { + show: { + ['/respondWith']: ['allIncomingItems', 'firstIncomingItem'], + }, + }, + default: '', + description: 'The name of the response field to put all items in', + placeholder: 'e.g. data', + }, ], }, ], @@ -229,13 +268,26 @@ export class RespondToWebhook implements INodeType { if (typeof responseBodyParameter === 'object') { responseBody = responseBodyParameter; } else { - responseBody = jsonParse(responseBodyParameter, { - errorMessage: "Invalid JSON in 'Response Body' field", - }); + try { + responseBody = jsonParse(responseBodyParameter); + } catch (error) { + throw new NodeOperationError(this.getNode(), error as Error, { + message: "Invalid JSON in 'Response Body' field", + description: + "Check that the syntax of the JSON in the 'Response Body' parameter is valid", + }); + } } } + } else if (respondWith === 'allIncomingItems') { + const respondItems = items.map((item) => item.json); + responseBody = options.responseKey + ? set({}, options.responseKey as string, respondItems) + : respondItems; } else if (respondWith === 'firstIncomingItem') { - responseBody = items[0].json; + responseBody = options.responseKey + ? set({}, options.responseKey as string, items[0].json) + : items[0].json; } else if (respondWith === 'text') { responseBody = this.getNodeParameter('responseBody', 0) as string; } else if (respondWith === 'binary') { @@ -270,7 +322,7 @@ export class RespondToWebhook implements INodeType { if (!headers['content-type']) { headers['content-type'] = binaryData.mimeType; } - } else if (respondWith == 'redirect') { + } else if (respondWith === 'redirect') { headers.location = this.getNodeParameter('redirectURL', 0) as string; statusCode = (options.responseCode as number) ?? 307; } else if (respondWith !== 'noData') {