mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
✨ Make it possible to return custom content-type and data with
webhook
This commit is contained in:
parent
1173c998fc
commit
ded2152d61
|
@ -1,4 +1,5 @@
|
||||||
import * as express from 'express';
|
import * as express from 'express';
|
||||||
|
import { get } from 'lodash';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ActiveExecutions,
|
ActiveExecutions,
|
||||||
|
@ -275,31 +276,63 @@ export function getWorkflowWebhooks(workflow: Workflow, additionalData: IWorkflo
|
||||||
if (responseData === 'firstEntryJson') {
|
if (responseData === 'firstEntryJson') {
|
||||||
// Return the JSON data of the first entry
|
// Return the JSON data of the first entry
|
||||||
data = returnData.data!.main[0]![0].json;
|
data = returnData.data!.main[0]![0].json;
|
||||||
|
|
||||||
|
const responsePropertyName = webhookData.workflow.getSimpleParameterValue(workflowStartNode, webhookData.webhookDescription['responsePropertyName'], undefined);
|
||||||
|
|
||||||
|
if (responsePropertyName !== undefined) {
|
||||||
|
data = get(data, responsePropertyName as string) as IDataObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
const responseContentType = webhookData.workflow.getSimpleParameterValue(workflowStartNode, webhookData.webhookDescription['responseContentType'], undefined);
|
||||||
|
|
||||||
|
if (responseContentType !== undefined) {
|
||||||
|
// Send the webhook response manually to be able to set the content-type
|
||||||
|
res.setHeader('Content-Type', responseContentType as string);
|
||||||
|
|
||||||
|
// Returning an object, boolean, number, ... causes problems so make sure to stringify if needed
|
||||||
|
if (data !== null && data !== undefined && ['Buffer', 'String'].includes(data.constructor.name)) {
|
||||||
|
res.end(data);
|
||||||
|
} else {
|
||||||
|
res.end(JSON.stringify(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
responseCallback(null, {
|
||||||
|
noWebhookResponse: true,
|
||||||
|
});
|
||||||
|
didSendResponse = true;
|
||||||
|
}
|
||||||
|
|
||||||
} else if (responseData === 'firstEntryBinary') {
|
} else if (responseData === 'firstEntryBinary') {
|
||||||
// Return the binary data of the first entry
|
// Return the binary data of the first entry
|
||||||
data = returnData.data!.main[0]![0];
|
data = returnData.data!.main[0]![0];
|
||||||
if (data.binary === undefined) {
|
if (data.binary === undefined) {
|
||||||
responseCallback(new Error('No binary data to return got found.'), {});
|
responseCallback(new Error('No binary data to return got found.'), {});
|
||||||
|
didSendResponse = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const responseBinaryPropertyName = webhookData.workflow.getSimpleParameterValue(workflowStartNode, webhookData.webhookDescription['responseBinaryPropertyName'], 'data');
|
const responseBinaryPropertyName = webhookData.workflow.getSimpleParameterValue(workflowStartNode, webhookData.webhookDescription['responseBinaryPropertyName'], 'data');
|
||||||
|
|
||||||
if (responseBinaryPropertyName === undefined) {
|
if (responseBinaryPropertyName === undefined && didSendResponse === false) {
|
||||||
responseCallback(new Error('No "responseBinaryPropertyName" is set.'), {});
|
responseCallback(new Error('No "responseBinaryPropertyName" is set.'), {});
|
||||||
|
didSendResponse = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const binaryData = (data.binary as IBinaryKeyData)[responseBinaryPropertyName as string];
|
const binaryData = (data.binary as IBinaryKeyData)[responseBinaryPropertyName as string];
|
||||||
if (binaryData === undefined) {
|
if (binaryData === undefined && didSendResponse === false) {
|
||||||
responseCallback(new Error(`The binary property "${responseBinaryPropertyName}" which should be returned does not exist.`), {});
|
responseCallback(new Error(`The binary property "${responseBinaryPropertyName}" which should be returned does not exist.`), {});
|
||||||
|
didSendResponse = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the webhook response manually
|
if (didSendResponse === false) {
|
||||||
res.setHeader('Content-Type', binaryData.mimeType);
|
// Send the webhook response manually
|
||||||
res.end(Buffer.from(binaryData.data, BINARY_ENCODING));
|
res.setHeader('Content-Type', binaryData.mimeType);
|
||||||
|
res.end(Buffer.from(binaryData.data, BINARY_ENCODING));
|
||||||
|
|
||||||
|
responseCallback(null, {
|
||||||
|
noWebhookResponse: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
responseCallback(null, {
|
|
||||||
noWebhookResponse: true,
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
// Return the JSON data of all the entries
|
// Return the JSON data of all the entries
|
||||||
data = [];
|
data = [];
|
||||||
|
@ -308,10 +341,12 @@ export function getWorkflowWebhooks(workflow: Workflow, additionalData: IWorkflo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
responseCallback(null, {
|
if (didSendResponse === false) {
|
||||||
data,
|
responseCallback(null, {
|
||||||
responseCode,
|
data,
|
||||||
});
|
responseCode,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
didSendResponse = true;
|
didSendResponse = true;
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,8 @@ export class Webhook implements INodeType {
|
||||||
responseMode: '={{$parameter["responseMode"]}}',
|
responseMode: '={{$parameter["responseMode"]}}',
|
||||||
responseData: '={{$parameter["responseData"]}}',
|
responseData: '={{$parameter["responseData"]}}',
|
||||||
responseBinaryPropertyName: '={{$parameter["responseBinaryPropertyName"]}}',
|
responseBinaryPropertyName: '={{$parameter["responseBinaryPropertyName"]}}',
|
||||||
|
responseContentType: '={{$parameter["options"]["responseContentType"]}}',
|
||||||
|
responsePropertyName: '={{$parameter["options"]["responsePropertyName"]}}',
|
||||||
path: '={{$parameter["path"]}}',
|
path: '={{$parameter["path"]}}',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -203,6 +205,42 @@ export class Webhook implements INodeType {
|
||||||
},
|
},
|
||||||
description: 'Name of the binary property to return',
|
description: 'Name of the binary property to return',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
displayName: 'Options',
|
||||||
|
name: 'options',
|
||||||
|
type: 'collection',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
responseData: [
|
||||||
|
'firstEntryJson',
|
||||||
|
],
|
||||||
|
responseMode: [
|
||||||
|
'lastNode',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
placeholder: 'Add Option',
|
||||||
|
default: {},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
displayName: 'Response Content-Type',
|
||||||
|
name: 'responseContentType',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
placeholder: 'application/xml',
|
||||||
|
description: 'Set a custom content-type to return if another one as the "application/json" should be returned.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Property Name',
|
||||||
|
name: 'responsePropertyName',
|
||||||
|
type: 'string',
|
||||||
|
default: 'data',
|
||||||
|
description: 'Name of the property to return the data of instead of the whole JSON.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -467,6 +467,8 @@ export interface IWebhookDescription {
|
||||||
name: string;
|
name: string;
|
||||||
path: string;
|
path: string;
|
||||||
responseBinaryPropertyName?: string;
|
responseBinaryPropertyName?: string;
|
||||||
|
responseContentType?: string;
|
||||||
|
responsePropertyName?: string;
|
||||||
responseMode?: WebhookResponseMode | string;
|
responseMode?: WebhookResponseMode | string;
|
||||||
responseData?: WebhookResponseData | string;
|
responseData?: WebhookResponseData | string;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue