mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-18 02:21:13 +00:00
refactor(core): Extract functions from executeWebhook (#17152)
This commit is contained in:
@@ -371,38 +371,14 @@ export async function executeWebhook(
|
|||||||
additionalData.executionId = executionId;
|
additionalData.executionId = executionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if response mode should be set automatically, e.g. multipage form
|
const { responseMode, responseCode, responseData } = evaluateResponseOptions(
|
||||||
const responseMode =
|
|
||||||
autoDetectResponseMode(workflowStartNode, workflow, req.method) ??
|
|
||||||
(workflow.expression.getSimpleParameterValue(
|
|
||||||
workflowStartNode,
|
|
||||||
webhookData.webhookDescription.responseMode,
|
|
||||||
executionMode,
|
|
||||||
additionalKeys,
|
|
||||||
undefined,
|
|
||||||
'onReceived',
|
|
||||||
) as WebhookResponseMode);
|
|
||||||
|
|
||||||
const responseCode = workflow.expression.getSimpleParameterValue(
|
|
||||||
workflowStartNode,
|
workflowStartNode,
|
||||||
webhookData.webhookDescription.responseCode as string,
|
workflow,
|
||||||
|
req,
|
||||||
|
webhookData,
|
||||||
executionMode,
|
executionMode,
|
||||||
additionalKeys,
|
additionalKeys,
|
||||||
undefined,
|
);
|
||||||
200,
|
|
||||||
) as number;
|
|
||||||
|
|
||||||
// This parameter is used for two different purposes:
|
|
||||||
// 1. as arbitrary string input defined in the workflow in the "respond immediately" mode,
|
|
||||||
// 2. as well as WebhookResponseData config in all the other modes
|
|
||||||
const responseData = workflow.expression.getComplexParameterValue(
|
|
||||||
workflowStartNode,
|
|
||||||
webhookData.webhookDescription.responseData,
|
|
||||||
executionMode,
|
|
||||||
additionalKeys,
|
|
||||||
undefined,
|
|
||||||
'firstEntryJson',
|
|
||||||
) as WebhookResponseData | string | undefined;
|
|
||||||
|
|
||||||
if (!['onReceived', 'lastNode', 'responseNode', 'formPage', 'streaming'].includes(responseMode)) {
|
if (!['onReceived', 'lastNode', 'responseNode', 'formPage', 'streaming'].includes(responseMode)) {
|
||||||
// If the mode is not known we error. Is probably best like that instead of using
|
// If the mode is not known we error. Is probably best like that instead of using
|
||||||
@@ -417,21 +393,6 @@ export async function executeWebhook(
|
|||||||
additionalData.httpRequest = req;
|
additionalData.httpRequest = req;
|
||||||
additionalData.httpResponse = res;
|
additionalData.httpResponse = res;
|
||||||
|
|
||||||
let binaryData;
|
|
||||||
|
|
||||||
const nodeVersion = workflowStartNode.typeVersion;
|
|
||||||
if (nodeVersion === 1) {
|
|
||||||
// binaryData option is removed in versions higher than 1
|
|
||||||
binaryData = workflow.expression.getSimpleParameterValue(
|
|
||||||
workflowStartNode,
|
|
||||||
'={{$parameter["options"]["binaryData"]}}',
|
|
||||||
executionMode,
|
|
||||||
additionalKeys,
|
|
||||||
undefined,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let didSendResponse = false;
|
let didSendResponse = false;
|
||||||
let runExecutionDataMerge = {};
|
let runExecutionDataMerge = {};
|
||||||
try {
|
try {
|
||||||
@@ -439,28 +400,7 @@ export async function executeWebhook(
|
|||||||
// the workflow should be executed or not
|
// the workflow should be executed or not
|
||||||
let webhookResultData: IWebhookResponseData;
|
let webhookResultData: IWebhookResponseData;
|
||||||
|
|
||||||
// if `Webhook` or `Wait` node, and binaryData is enabled, skip pre-parse the request-body
|
await parseRequestBody(req, workflowStartNode, workflow, executionMode, additionalKeys);
|
||||||
// always falsy for versions higher than 1
|
|
||||||
if (!binaryData) {
|
|
||||||
const { contentType } = req;
|
|
||||||
if (contentType === 'multipart/form-data') {
|
|
||||||
req.body = await parseFormData(req);
|
|
||||||
} else {
|
|
||||||
if (nodeVersion > 1) {
|
|
||||||
if (
|
|
||||||
contentType?.startsWith('application/json') ||
|
|
||||||
contentType?.startsWith('text/plain') ||
|
|
||||||
contentType?.startsWith('application/x-www-form-urlencoded') ||
|
|
||||||
contentType?.endsWith('/xml') ||
|
|
||||||
contentType?.endsWith('+xml')
|
|
||||||
) {
|
|
||||||
await parseBody(req);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
await parseBody(req);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: remove this hack, and make sure that execution data is properly created before the MCP trigger is executed
|
// TODO: remove this hack, and make sure that execution data is properly created before the MCP trigger is executed
|
||||||
if (workflowStartNode.type === MCP_TRIGGER_NODE_TYPE) {
|
if (workflowStartNode.type === MCP_TRIGGER_NODE_TYPE) {
|
||||||
@@ -565,7 +505,7 @@ export async function executeWebhook(
|
|||||||
|
|
||||||
if (!res.headersSent) {
|
if (!res.headersSent) {
|
||||||
// Only set given headers if they haven't been sent yet, e.g. for streaming
|
// Only set given headers if they haven't been sent yet, e.g. for streaming
|
||||||
if (responseHeaders !== undefined && responseHeaders.entries !== undefined) {
|
if (responseHeaders?.entries !== undefined) {
|
||||||
for (const item of responseHeaders.entries) {
|
for (const item of responseHeaders.entries) {
|
||||||
res.setHeader(item.name, item.value);
|
res.setHeader(item.name, item.value);
|
||||||
}
|
}
|
||||||
@@ -924,3 +864,102 @@ export async function executeWebhook(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates the response mode, code and data for a webhook node
|
||||||
|
*/
|
||||||
|
function evaluateResponseOptions(
|
||||||
|
workflowStartNode: INode,
|
||||||
|
workflow: Workflow,
|
||||||
|
req: WebhookRequest,
|
||||||
|
webhookData: IWebhookData,
|
||||||
|
executionMode: WorkflowExecuteMode,
|
||||||
|
additionalKeys: IWorkflowDataProxyAdditionalKeys,
|
||||||
|
) {
|
||||||
|
//check if response mode should be set automatically, e.g. multipage form
|
||||||
|
const responseMode =
|
||||||
|
autoDetectResponseMode(workflowStartNode, workflow, req.method) ??
|
||||||
|
(workflow.expression.getSimpleParameterValue(
|
||||||
|
workflowStartNode,
|
||||||
|
webhookData.webhookDescription.responseMode,
|
||||||
|
executionMode,
|
||||||
|
additionalKeys,
|
||||||
|
undefined,
|
||||||
|
'onReceived',
|
||||||
|
) as WebhookResponseMode);
|
||||||
|
|
||||||
|
const responseCode = workflow.expression.getSimpleParameterValue(
|
||||||
|
workflowStartNode,
|
||||||
|
webhookData.webhookDescription.responseCode as string,
|
||||||
|
executionMode,
|
||||||
|
additionalKeys,
|
||||||
|
undefined,
|
||||||
|
200,
|
||||||
|
) as number;
|
||||||
|
|
||||||
|
// This parameter is used for two different purposes:
|
||||||
|
// 1. as arbitrary string input defined in the workflow in the "respond immediately" mode,
|
||||||
|
// 2. as well as WebhookResponseData config in all the other modes
|
||||||
|
const responseData = workflow.expression.getComplexParameterValue(
|
||||||
|
workflowStartNode,
|
||||||
|
webhookData.webhookDescription.responseData,
|
||||||
|
executionMode,
|
||||||
|
additionalKeys,
|
||||||
|
undefined,
|
||||||
|
'firstEntryJson',
|
||||||
|
) as WebhookResponseData | string | undefined;
|
||||||
|
|
||||||
|
return { responseMode, responseCode, responseData };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the request body (form, xml, json, form-urlencoded, etc.) if needed
|
||||||
|
* into the `req.body` property.
|
||||||
|
*/
|
||||||
|
async function parseRequestBody(
|
||||||
|
req: WebhookRequest,
|
||||||
|
workflowStartNode: INode,
|
||||||
|
workflow: Workflow,
|
||||||
|
executionMode: WorkflowExecuteMode,
|
||||||
|
additionalKeys: IWorkflowDataProxyAdditionalKeys,
|
||||||
|
) {
|
||||||
|
let binaryData: string | number | boolean | unknown[] | undefined;
|
||||||
|
|
||||||
|
const nodeVersion = workflowStartNode.typeVersion;
|
||||||
|
if (nodeVersion === 1) {
|
||||||
|
// binaryData option is removed in versions higher than 1
|
||||||
|
binaryData = workflow.expression.getSimpleParameterValue(
|
||||||
|
workflowStartNode,
|
||||||
|
'={{$parameter["options"]["binaryData"]}}',
|
||||||
|
executionMode,
|
||||||
|
additionalKeys,
|
||||||
|
undefined,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if `Webhook` or `Wait` node, and binaryData is enabled, skip pre-parse the request-body
|
||||||
|
// always falsy for versions higher than 1
|
||||||
|
if (binaryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { contentType } = req;
|
||||||
|
if (contentType === 'multipart/form-data') {
|
||||||
|
req.body = await parseFormData(req);
|
||||||
|
} else {
|
||||||
|
if (nodeVersion > 1) {
|
||||||
|
if (
|
||||||
|
contentType?.startsWith('application/json') ||
|
||||||
|
contentType?.startsWith('text/plain') ||
|
||||||
|
contentType?.startsWith('application/x-www-form-urlencoded') ||
|
||||||
|
contentType?.endsWith('/xml') ||
|
||||||
|
contentType?.endsWith('+xml')
|
||||||
|
) {
|
||||||
|
await parseBody(req);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await parseBody(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user