n8n/packages/nodes-base/nodes/RespondToWebhook/RespondToWebhook.node.ts

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

271 lines
6.7 KiB
TypeScript
Raw Normal View History

import type { Readable } from 'stream';
import type {
IDataObject,
IExecuteFunctions,
IN8nHttpFullResponse,
IN8nHttpResponse,
INodeExecutionData,
INodeType,
INodeTypeDescription,
} from 'n8n-workflow';
import { jsonParse, BINARY_ENCODING, NodeOperationError } from 'n8n-workflow';
export class RespondToWebhook implements INodeType {
description: INodeTypeDescription = {
displayName: 'Respond to Webhook',
icon: 'file:webhook.svg',
name: 'respondToWebhook',
group: ['transform'],
version: 1,
description: 'Returns data for Webhook',
defaults: {
name: 'Respond to Webhook',
},
inputs: ['main'],
outputs: ['main'],
credentials: [],
properties: [
{
displayName: 'Respond With',
name: 'respondWith',
type: 'options',
options: [
{
refactor: Apply more `eslint-plugin-n8n-nodes-base` autofixable rules (#3432) * :zap: Update `lintfix` script * :shirt: Remove unneeded lint exceptions * :shirt: Run baseline `lintfix` * :shirt: Apply `node-param-description-miscased-url` (#3441) * :shirt: Apply `rule node-param-placeholder-miscased-id` (#3443) Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * :shirt: Apply `node-param-option-name-wrong-for-upsert` (#3446) * :shirt: Apply `node-param-min-value-wrong-for-limit` (#3442) Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * Apply `node-param-display-name-wrong-for-dynamic-options` (#3454) * :hammer: fix * :zap: Fix `Assigned To` fields Co-authored-by: Michael Kret <michael.k@radency.com> * :shirt: Apply `rule node-param-default-wrong-for-number` (#3453) * :shirt: Apply `node-param-default-wrong-for-string` (#3452) Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * Apply `node-param-display-name-miscased` (#3449) * :hammer: fix * :hammer: exceptions * :zap: review fixes * :shirt: Apply `node-param-description-lowercase-first-char` (#3451) * :zap: fix * :zap: review fixes * :zap: fix Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * :shirt: Apply `node-param-description-wrong-for-dynamic-options` (#3456) * Rule working as intended * Add rule * :fire: Remove repetitions * :shirt: Add exceptions Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * :shirt: Small fix for `node-param-description-wrong-for-dynamic-options` * :shirt: Apply `node-param-default-wrong-for-fixed-collection` (#3460) * :shirt: Apply `node-param-description-line-break-html-tag` (#3462) * :shirt: Run baseline `lintfix` * :shirt: Apply `node-param-options-type-unsorted-items` (#3459) * :zap: fix * :hammer: exceptions * Add exception for Salesmate and Zoom Co-authored-by: Michael Kret <michael.k@radency.com> Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * :zap: Restore `lintfix` command Co-authored-by: Omar Ajoue <krynble@gmail.com> Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com> Co-authored-by: agobrech <45268029+agobrech@users.noreply.github.com> Co-authored-by: Michael Kret <michael.k@radency.com> Co-authored-by: brianinoa <54530642+brianinoa@users.noreply.github.com>
2022-06-03 10:23:49 -07:00
name: 'Binary',
value: 'binary',
},
{
refactor: Apply more `eslint-plugin-n8n-nodes-base` autofixable rules (#3432) * :zap: Update `lintfix` script * :shirt: Remove unneeded lint exceptions * :shirt: Run baseline `lintfix` * :shirt: Apply `node-param-description-miscased-url` (#3441) * :shirt: Apply `rule node-param-placeholder-miscased-id` (#3443) Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * :shirt: Apply `node-param-option-name-wrong-for-upsert` (#3446) * :shirt: Apply `node-param-min-value-wrong-for-limit` (#3442) Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * Apply `node-param-display-name-wrong-for-dynamic-options` (#3454) * :hammer: fix * :zap: Fix `Assigned To` fields Co-authored-by: Michael Kret <michael.k@radency.com> * :shirt: Apply `rule node-param-default-wrong-for-number` (#3453) * :shirt: Apply `node-param-default-wrong-for-string` (#3452) Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * Apply `node-param-display-name-miscased` (#3449) * :hammer: fix * :hammer: exceptions * :zap: review fixes * :shirt: Apply `node-param-description-lowercase-first-char` (#3451) * :zap: fix * :zap: review fixes * :zap: fix Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * :shirt: Apply `node-param-description-wrong-for-dynamic-options` (#3456) * Rule working as intended * Add rule * :fire: Remove repetitions * :shirt: Add exceptions Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * :shirt: Small fix for `node-param-description-wrong-for-dynamic-options` * :shirt: Apply `node-param-default-wrong-for-fixed-collection` (#3460) * :shirt: Apply `node-param-description-line-break-html-tag` (#3462) * :shirt: Run baseline `lintfix` * :shirt: Apply `node-param-options-type-unsorted-items` (#3459) * :zap: fix * :hammer: exceptions * Add exception for Salesmate and Zoom Co-authored-by: Michael Kret <michael.k@radency.com> Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * :zap: Restore `lintfix` command Co-authored-by: Omar Ajoue <krynble@gmail.com> Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com> Co-authored-by: agobrech <45268029+agobrech@users.noreply.github.com> Co-authored-by: Michael Kret <michael.k@radency.com> Co-authored-by: brianinoa <54530642+brianinoa@users.noreply.github.com>
2022-06-03 10:23:49 -07:00
name: 'First Incoming Item',
value: 'firstIncomingItem',
},
{
name: 'JSON',
value: 'json',
},
{
name: 'No Data',
value: 'noData',
},
refactor: Apply more `eslint-plugin-n8n-nodes-base` autofixable rules (#3432) * :zap: Update `lintfix` script * :shirt: Remove unneeded lint exceptions * :shirt: Run baseline `lintfix` * :shirt: Apply `node-param-description-miscased-url` (#3441) * :shirt: Apply `rule node-param-placeholder-miscased-id` (#3443) Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * :shirt: Apply `node-param-option-name-wrong-for-upsert` (#3446) * :shirt: Apply `node-param-min-value-wrong-for-limit` (#3442) Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * Apply `node-param-display-name-wrong-for-dynamic-options` (#3454) * :hammer: fix * :zap: Fix `Assigned To` fields Co-authored-by: Michael Kret <michael.k@radency.com> * :shirt: Apply `rule node-param-default-wrong-for-number` (#3453) * :shirt: Apply `node-param-default-wrong-for-string` (#3452) Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * Apply `node-param-display-name-miscased` (#3449) * :hammer: fix * :hammer: exceptions * :zap: review fixes * :shirt: Apply `node-param-description-lowercase-first-char` (#3451) * :zap: fix * :zap: review fixes * :zap: fix Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * :shirt: Apply `node-param-description-wrong-for-dynamic-options` (#3456) * Rule working as intended * Add rule * :fire: Remove repetitions * :shirt: Add exceptions Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * :shirt: Small fix for `node-param-description-wrong-for-dynamic-options` * :shirt: Apply `node-param-default-wrong-for-fixed-collection` (#3460) * :shirt: Apply `node-param-description-line-break-html-tag` (#3462) * :shirt: Run baseline `lintfix` * :shirt: Apply `node-param-options-type-unsorted-items` (#3459) * :zap: fix * :hammer: exceptions * Add exception for Salesmate and Zoom Co-authored-by: Michael Kret <michael.k@radency.com> Co-authored-by: Iván Ovejero <ivov.src@gmail.com> * :zap: Restore `lintfix` command Co-authored-by: Omar Ajoue <krynble@gmail.com> Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com> Co-authored-by: agobrech <45268029+agobrech@users.noreply.github.com> Co-authored-by: Michael Kret <michael.k@radency.com> Co-authored-by: brianinoa <54530642+brianinoa@users.noreply.github.com>
2022-06-03 10:23:49 -07:00
{
name: 'Text',
value: 'text',
},
],
default: 'firstIncomingItem',
description: 'The data that should be returned',
},
{
displayName:
'When using expressions, note that this node will only run for the first item in the input data.',
name: 'webhookNotice',
type: 'notice',
displayOptions: {
show: {
respondWith: ['json', 'text'],
},
},
default: '',
},
{
displayName: 'Response Body',
name: 'responseBody',
type: 'json',
displayOptions: {
show: {
respondWith: ['json'],
},
},
default: '',
placeholder: '{ "key": "value" }',
description: 'The HTTP Response JSON data',
},
{
displayName: 'Response Body',
name: 'responseBody',
type: 'string',
displayOptions: {
show: {
respondWith: ['text'],
},
},
default: '',
placeholder: 'e.g. Workflow started',
description: 'The HTTP Response text data',
},
{
displayName: 'Response Data Source',
name: 'responseDataSource',
type: 'options',
displayOptions: {
show: {
respondWith: ['binary'],
},
},
options: [
{
name: 'Choose Automatically From Input',
value: 'automatically',
description: 'Use if input data will contain a single piece of binary data',
},
{
name: 'Specify Myself',
value: 'set',
description: 'Enter the name of the input field the binary data will be in',
},
],
default: 'automatically',
},
{
displayName: 'Input Field Name',
name: 'inputFieldName',
type: 'string',
required: true,
default: 'data',
displayOptions: {
show: {
respondWith: ['binary'],
responseDataSource: ['set'],
},
},
description: 'The name of the node input field with the binary data',
},
{
displayName: 'Options',
name: 'options',
type: 'collection',
placeholder: 'Add Option',
default: {},
options: [
{
displayName: 'Response Code',
name: 'responseCode',
type: 'number',
typeOptions: {
minValue: 100,
maxValue: 599,
},
default: 200,
description: 'The HTTP Response code to return. Defaults to 200.',
},
{
displayName: 'Response Headers',
name: 'responseHeaders',
placeholder: 'Add Response Header',
description: 'Add headers to the webhook response',
type: 'fixedCollection',
typeOptions: {
multipleValues: true,
},
default: {},
options: [
{
name: 'entries',
displayName: 'Entries',
values: [
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
description: 'Name of the header',
},
{
displayName: 'Value',
name: 'value',
type: 'string',
default: '',
description: 'Value of the header',
},
],
},
],
},
],
},
],
};
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData();
const respondWith = this.getNodeParameter('respondWith', 0) as string;
const options = this.getNodeParameter('options', 0, {});
const headers = {} as IDataObject;
if (options.responseHeaders) {
for (const header of (options.responseHeaders as IDataObject).entries as IDataObject[]) {
if (typeof header.name !== 'string') {
header.name = header.name?.toString();
}
headers[header.name?.toLowerCase() as string] = header.value?.toString();
}
}
let responseBody: IN8nHttpResponse | Readable;
if (respondWith === 'json') {
const responseBodyParameter = this.getNodeParameter('responseBody', 0) as string;
if (responseBodyParameter) {
if (typeof responseBodyParameter === 'object') {
responseBody = responseBodyParameter;
} else {
responseBody = jsonParse(responseBodyParameter, {
errorMessage: "Invalid JSON in 'Response Body' field",
});
}
}
} else if (respondWith === 'firstIncomingItem') {
responseBody = items[0].json;
} else if (respondWith === 'text') {
responseBody = this.getNodeParameter('responseBody', 0) as string;
} else if (respondWith === 'binary') {
const item = items[0];
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on the first item!');
}
let responseBinaryPropertyName: string;
const responseDataSource = this.getNodeParameter('responseDataSource', 0) as string;
if (responseDataSource === 'set') {
responseBinaryPropertyName = this.getNodeParameter('inputFieldName', 0) as string;
} else {
const binaryKeys = Object.keys(item.binary);
if (binaryKeys.length === 0) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on the first item!');
}
responseBinaryPropertyName = binaryKeys[0];
}
const binaryData = this.helpers.assertBinaryData(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;
}
} else if (respondWith !== 'noData') {
throw new NodeOperationError(
this.getNode(),
`The Response Data option "${respondWith}" is not supported!`,
);
}
const response: IN8nHttpFullResponse = {
body: responseBody,
headers,
statusCode: (options.responseCode as number) || 200,
};
this.sendResponse(response);
return [items];
}
}