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

@@ -4,14 +4,19 @@ import { Service } from 'typedi';
import type {
IWebhookData,
IWorkflowExecuteAdditionalData,
WebhookHttpMethod,
IHttpRequestMethods,
Workflow,
WorkflowActivateMode,
WorkflowExecuteMode,
} from 'n8n-workflow';
import { ActiveWebhooks } from '@/ActiveWebhooks';
import type { IResponseCallbackData, IWorkflowDb } from '@/Interfaces';
import type {
IResponseCallbackData,
IWebhookManager,
IWorkflowDb,
WebhookRequest,
} from '@/Interfaces';
import { Push } from '@/push';
import * as ResponseHelper from '@/ResponseHelper';
import * as WebhookHelpers from '@/WebhookHelpers';
@@ -21,7 +26,7 @@ const WEBHOOK_TEST_UNREGISTERED_HINT =
"Click the 'Execute workflow' button on the canvas, then try again. (In test mode, the webhook only works for one call after you click this button)";
@Service()
export class TestWebhooks {
export class TestWebhooks implements IWebhookManager {
private testWebhookData: {
[key: string]: {
sessionId?: string;
@@ -44,14 +49,12 @@ export class TestWebhooks {
* data gets additionally send to the UI. After the request got handled it
* automatically remove the test-webhook.
*/
async callTestWebhook(
httpMethod: WebhookHttpMethod,
path: string,
request: express.Request,
async executeWebhook(
request: WebhookRequest,
response: express.Response,
): Promise<IResponseCallbackData> {
// Reset request parameters
request.params = {};
const httpMethod = request.method;
let path = request.params.path;
// Remove trailing slash
if (path.endsWith('/')) {
@@ -82,6 +85,7 @@ export class TestWebhooks {
path.split('/').forEach((ele, index) => {
if (ele.startsWith(':')) {
// write params to req.params
// @ts-ignore
request.params[ele.slice(1)] = pathElements[index];
}
});
@@ -157,7 +161,7 @@ export class TestWebhooks {
/**
* Gets all request methods associated with a single test webhook
*/
async getWebhookMethods(path: string): Promise<string[]> {
async getWebhookMethods(path: string): Promise<IHttpRequestMethods[]> {
const webhookMethods = this.activeWebhooks.getWebhookMethods(path);
if (!webhookMethods.length) {
// The requested webhook is not registered