refactor(core): Parse Webhook request bodies on-demand (#6394)

Also,
1. Consistent CORS support ~on all three webhook types~ waiting webhooks never supported CORS. I'll fix that in another PR
2. [Fixes binary-data handling when request body is text, json, or xml](https://linear.app/n8n/issue/NODE-505/webhook-binary-data-handling-fails-for-textplain-files).
3. Reduced number of middleware that each request has to go through.
4. Removed the need to maintain webhook endpoints in the auth-exception list.
5. Skip all middlewares (apart from `compression`) on Webhook routes. 
6. move `multipart/form-data` support out of individual nodes
7. upgrade `formidable`
8. fix the filenames on binary-data in webhooks nodes
9. add unit tests and integration tests for webhook request handling, and increase test coverage
This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™
2023-08-01 17:32:30 +02:00
committed by GitHub
parent 369a2e9796
commit 31d8f478ee
29 changed files with 905 additions and 604 deletions

View File

@@ -1,11 +1,11 @@
import { WorkflowExecute } from 'n8n-core';
import type { INodeTypes, IRun } from 'n8n-workflow';
import type { INodeTypes, IRun, IRunExecutionData } from 'n8n-workflow';
import { createDeferredPromise, Workflow } from 'n8n-workflow';
import * as Helpers from './Helpers';
import type { WorkflowTestData } from './types';
export async function executeWorkflow(testData: WorkflowTestData, nodeTypes: INodeTypes) {
const executionMode = 'manual';
const executionMode = testData.trigger?.mode ?? 'manual';
const workflowInstance = new Workflow({
id: 'test',
nodes: testData.input.workflowData.nodes,
@@ -21,9 +21,30 @@ export async function executeWorkflow(testData: WorkflowTestData, nodeTypes: INo
nodeExecutionOrder,
testData,
);
const workflowExecute = new WorkflowExecute(additionalData, executionMode);
const executionData = await workflowExecute.run(workflowInstance);
let executionData: IRun;
const runExecutionData: IRunExecutionData = {
resultData: {
runData: {},
},
executionData: {
contextData: {},
waitingExecution: {},
waitingExecutionSource: null,
nodeExecutionStack: [
{
node: workflowInstance.getStartNode()!,
data: {
main: [[testData.trigger?.input ?? { json: {} }]],
},
source: null,
},
],
},
};
const workflowExecute = new WorkflowExecute(additionalData, executionMode, runExecutionData);
executionData = await workflowExecute.processRunExecutionData(workflowInstance);
const result = await waitPromise.promise();
return { executionData, result, nodeExecutionOrder };
}

View File

@@ -182,6 +182,7 @@ export function WorkflowExecuteAdditionalData(
webhookTestBaseUrl: 'webhook-test',
userId: '123',
variables: {},
instanceBaseUrl: '',
};
}
@@ -353,7 +354,9 @@ export const workflowToTests = (workflowFiles: string[]) => {
const testCases: WorkflowTestData[] = [];
for (const filePath of workflowFiles) {
const description = filePath.replace('.json', '');
const workflowData = readJsonFileSync<IWorkflowBase>(filePath);
const workflowData = readJsonFileSync<IWorkflowBase & Pick<WorkflowTestData, 'trigger'>>(
filePath,
);
const testDir = path.join(baseDir, path.dirname(filePath));
workflowData.nodes.forEach((node) => {
if (node.parameters) {
@@ -367,13 +370,15 @@ export const workflowToTests = (workflowFiles: string[]) => {
}
const nodeData = preparePinData(workflowData.pinData);
delete workflowData.pinData;
const { trigger } = workflowData;
delete workflowData.trigger;
const input = { workflowData };
const output = { nodeData };
testCases.push({ description, input, output });
testCases.push({ description, input, output, trigger });
}
return testCases;
};