mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-24 20:24:05 -08:00
refactor(core): Reorganize webhook related components under src/webhooks (no-changelog) (#10296)
Some checks are pending
Test Master / install-and-build (push) Waiting to run
Test Master / Unit tests (18.x) (push) Blocked by required conditions
Test Master / Unit tests (20.x) (push) Blocked by required conditions
Test Master / Unit tests (22.4) (push) Blocked by required conditions
Test Master / Lint (push) Blocked by required conditions
Test Master / Notify Slack on failure (push) Blocked by required conditions
Some checks are pending
Test Master / install-and-build (push) Waiting to run
Test Master / Unit tests (18.x) (push) Blocked by required conditions
Test Master / Unit tests (20.x) (push) Blocked by required conditions
Test Master / Unit tests (22.4) (push) Blocked by required conditions
Test Master / Lint (push) Blocked by required conditions
Test Master / Notify Slack on failure (push) Blocked by required conditions
This commit is contained in:
parent
2a8f1753e8
commit
c8d322a9ba
|
@ -13,15 +13,15 @@ import { N8nInstanceType } from '@/Interfaces';
|
||||||
import { ExternalHooks } from '@/ExternalHooks';
|
import { ExternalHooks } from '@/ExternalHooks';
|
||||||
import { send, sendErrorResponse } from '@/ResponseHelper';
|
import { send, sendErrorResponse } from '@/ResponseHelper';
|
||||||
import { rawBodyReader, bodyParser, corsMiddleware } from '@/middlewares';
|
import { rawBodyReader, bodyParser, corsMiddleware } from '@/middlewares';
|
||||||
import { TestWebhooks } from '@/TestWebhooks';
|
|
||||||
import { WaitingForms } from '@/WaitingForms';
|
import { WaitingForms } from '@/WaitingForms';
|
||||||
import { WaitingWebhooks } from '@/WaitingWebhooks';
|
import { TestWebhooks } from '@/webhooks/TestWebhooks';
|
||||||
import { webhookRequestHandler } from '@/WebhookHelpers';
|
import { WaitingWebhooks } from '@/webhooks/WaitingWebhooks';
|
||||||
|
import { webhookRequestHandler } from '@/webhooks/WebhookHelpers';
|
||||||
|
import { ActiveWebhooks } from '@/webhooks/ActiveWebhooks';
|
||||||
import { generateHostInstanceId } from './databases/utils/generators';
|
import { generateHostInstanceId } from './databases/utils/generators';
|
||||||
import { Logger } from '@/Logger';
|
import { Logger } from '@/Logger';
|
||||||
import { ServiceUnavailableError } from './errors/response-errors/service-unavailable.error';
|
import { ServiceUnavailableError } from './errors/response-errors/service-unavailable.error';
|
||||||
import { OnShutdown } from '@/decorators/OnShutdown';
|
import { OnShutdown } from '@/decorators/OnShutdown';
|
||||||
import { ActiveWebhooks } from '@/ActiveWebhooks';
|
|
||||||
import { GlobalConfig } from '@n8n/config';
|
import { GlobalConfig } from '@n8n/config';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
|
|
|
@ -27,7 +27,7 @@ import {
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
import type { IWorkflowDb } from '@/Interfaces';
|
import type { IWorkflowDb } from '@/Interfaces';
|
||||||
import * as WebhookHelpers from '@/WebhookHelpers';
|
import * as WebhookHelpers from '@/webhooks/WebhookHelpers';
|
||||||
import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData';
|
import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData';
|
||||||
|
|
||||||
import type { WorkflowEntity } from '@db/entities/WorkflowEntity';
|
import type { WorkflowEntity } from '@db/entities/WorkflowEntity';
|
||||||
|
@ -40,7 +40,7 @@ import {
|
||||||
} from '@/constants';
|
} from '@/constants';
|
||||||
import { NodeTypes } from '@/NodeTypes';
|
import { NodeTypes } from '@/NodeTypes';
|
||||||
import { ExternalHooks } from '@/ExternalHooks';
|
import { ExternalHooks } from '@/ExternalHooks';
|
||||||
import { WebhookService } from './services/webhook.service';
|
import { WebhookService } from '@/webhooks/webhook.service';
|
||||||
import { Logger } from './Logger';
|
import { Logger } from './Logger';
|
||||||
import { WorkflowRepository } from '@db/repositories/workflow.repository';
|
import { WorkflowRepository } from '@db/repositories/workflow.repository';
|
||||||
import { OrchestrationService } from '@/services/orchestration.service';
|
import { OrchestrationService } from '@/services/orchestration.service';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { Application, Request, Response } from 'express';
|
import type { Application } from 'express';
|
||||||
import type {
|
import type {
|
||||||
ExecutionError,
|
ExecutionError,
|
||||||
ICredentialDataDecryptedObject,
|
ICredentialDataDecryptedObject,
|
||||||
|
@ -22,7 +22,6 @@ import type {
|
||||||
FeatureFlags,
|
FeatureFlags,
|
||||||
INodeProperties,
|
INodeProperties,
|
||||||
IUserSettings,
|
IUserSettings,
|
||||||
IHttpRequestMethods,
|
|
||||||
StartNodeData,
|
StartNodeData,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
@ -239,34 +238,6 @@ export interface IExternalHooksFunctions {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type WebhookCORSRequest = Request & { method: 'OPTIONS' };
|
|
||||||
|
|
||||||
export type WebhookRequest = Request<{ path: string }> & {
|
|
||||||
method: IHttpRequestMethods;
|
|
||||||
params: Record<string, string>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type WaitingWebhookRequest = WebhookRequest & {
|
|
||||||
params: WebhookRequest['path'] & { suffix?: string };
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface WebhookAccessControlOptions {
|
|
||||||
allowedOrigins?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IWebhookManager {
|
|
||||||
/** Gets all request methods associated with a webhook path*/
|
|
||||||
getWebhookMethods?: (path: string) => Promise<IHttpRequestMethods[]>;
|
|
||||||
|
|
||||||
/** Find the CORS options matching a path and method */
|
|
||||||
findAccessControlOptions?: (
|
|
||||||
path: string,
|
|
||||||
httpMethod: IHttpRequestMethods,
|
|
||||||
) => Promise<WebhookAccessControlOptions | undefined>;
|
|
||||||
|
|
||||||
executeWebhook(req: WebhookRequest, res: Response): Promise<IResponseCallbackData>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IVersionNotificationSettings {
|
export interface IVersionNotificationSettings {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
endpoint: string;
|
endpoint: string;
|
||||||
|
@ -466,13 +437,6 @@ export interface IPushDataWorkerStatusPayload {
|
||||||
version: string;
|
version: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IResponseCallbackData {
|
|
||||||
data?: IDataObject | IDataObject[];
|
|
||||||
headers?: object;
|
|
||||||
noWebhookResponse?: boolean;
|
|
||||||
responseCode?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface INodesTypeData {
|
export interface INodesTypeData {
|
||||||
[key: string]: {
|
[key: string]: {
|
||||||
className: string;
|
className: string;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Service } from 'typedi';
|
import { Service } from 'typedi';
|
||||||
|
|
||||||
import type { IExecutionResponse } from '@/Interfaces';
|
import type { IExecutionResponse } from '@/Interfaces';
|
||||||
import { WaitingWebhooks } from '@/WaitingWebhooks';
|
import { WaitingWebhooks } from '@/webhooks/WaitingWebhooks';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class WaitingForms extends WaitingWebhooks {
|
export class WaitingForms extends WaitingWebhooks {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { ApplicationError } from 'n8n-workflow';
|
||||||
|
|
||||||
import config from '@/config';
|
import config from '@/config';
|
||||||
import { ActiveExecutions } from '@/ActiveExecutions';
|
import { ActiveExecutions } from '@/ActiveExecutions';
|
||||||
import { WebhookServer } from '@/WebhookServer';
|
import { WebhookServer } from '@/webhooks/WebhookServer';
|
||||||
import { Queue } from '@/Queue';
|
import { Queue } from '@/Queue';
|
||||||
import { BaseCommand } from './BaseCommand';
|
import { BaseCommand } from './BaseCommand';
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ export class Webhook extends BaseCommand {
|
||||||
await this.initExternalHooks();
|
await this.initExternalHooks();
|
||||||
this.logger.debug('External hooks init complete');
|
this.logger.debug('External hooks init complete');
|
||||||
await this.initExternalSecrets();
|
await this.initExternalSecrets();
|
||||||
this.logger.debug('External seecrets init complete');
|
this.logger.debug('External secrets init complete');
|
||||||
}
|
}
|
||||||
|
|
||||||
async run() {
|
async run() {
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { Workflow, sleep, ApplicationError } from 'n8n-workflow';
|
||||||
|
|
||||||
import * as Db from '@/Db';
|
import * as Db from '@/Db';
|
||||||
import * as ResponseHelper from '@/ResponseHelper';
|
import * as ResponseHelper from '@/ResponseHelper';
|
||||||
import * as WebhookHelpers from '@/WebhookHelpers';
|
import * as WebhookHelpers from '@/webhooks/WebhookHelpers';
|
||||||
import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData';
|
import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData';
|
||||||
import config from '@/config';
|
import config from '@/config';
|
||||||
import type { Job, JobId, JobResponse, WebhookResponse } from '@/Queue';
|
import type { Job, JobId, JobResponse, WebhookResponse } from '@/Queue';
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { License } from '@/License';
|
||||||
import { Logger } from '@/Logger';
|
import { Logger } from '@/Logger';
|
||||||
import { ActiveWorkflowManager } from '@/ActiveWorkflowManager';
|
import { ActiveWorkflowManager } from '@/ActiveWorkflowManager';
|
||||||
import { Push } from '@/push';
|
import { Push } from '@/push';
|
||||||
import { TestWebhooks } from '@/TestWebhooks';
|
import { TestWebhooks } from '@/webhooks/TestWebhooks';
|
||||||
import { OrchestrationService } from '@/services/orchestration.service';
|
import { OrchestrationService } from '@/services/orchestration.service';
|
||||||
import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
|
import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
|
||||||
import { CommunityPackagesService } from '@/services/communityPackages.service';
|
import { CommunityPackagesService } from '@/services/communityPackages.service';
|
||||||
|
|
|
@ -5,20 +5,25 @@ import type { INode, IWebhookData, IHttpRequestMethods } from 'n8n-workflow';
|
||||||
|
|
||||||
import { WorkflowRepository } from '@db/repositories/workflow.repository';
|
import { WorkflowRepository } from '@db/repositories/workflow.repository';
|
||||||
import type {
|
import type {
|
||||||
IResponseCallbackData,
|
IWebhookResponseCallbackData,
|
||||||
IWebhookManager,
|
IWebhookManager,
|
||||||
WebhookAccessControlOptions,
|
WebhookAccessControlOptions,
|
||||||
WebhookRequest,
|
WebhookRequest,
|
||||||
} from '@/Interfaces';
|
} from './webhook.types';
|
||||||
import { Logger } from '@/Logger';
|
import { Logger } from '@/Logger';
|
||||||
import { NodeTypes } from '@/NodeTypes';
|
import { NodeTypes } from '@/NodeTypes';
|
||||||
import { WebhookService } from '@/services/webhook.service';
|
import { WebhookService } from '@/webhooks/webhook.service';
|
||||||
import { WebhookNotFoundError } from '@/errors/response-errors/webhook-not-found.error';
|
import { WebhookNotFoundError } from '@/errors/response-errors/webhook-not-found.error';
|
||||||
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
||||||
import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData';
|
import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData';
|
||||||
import * as WebhookHelpers from '@/WebhookHelpers';
|
import * as WebhookHelpers from '@/webhooks/WebhookHelpers';
|
||||||
import { WorkflowStaticDataService } from '@/workflows/workflowStaticData.service';
|
import { WorkflowStaticDataService } from '@/workflows/workflowStaticData.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for handling the execution of production webhooks, i.e. webhooks
|
||||||
|
* that belong to activated workflows and use the production URL
|
||||||
|
* (https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.webhook/#webhook-urls)
|
||||||
|
*/
|
||||||
@Service()
|
@Service()
|
||||||
export class ActiveWebhooks implements IWebhookManager {
|
export class ActiveWebhooks implements IWebhookManager {
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -57,7 +62,7 @@ export class ActiveWebhooks implements IWebhookManager {
|
||||||
async executeWebhook(
|
async executeWebhook(
|
||||||
request: WebhookRequest,
|
request: WebhookRequest,
|
||||||
response: Response,
|
response: Response,
|
||||||
): Promise<IResponseCallbackData> {
|
): Promise<IWebhookResponseCallbackData> {
|
||||||
const httpMethod = request.method;
|
const httpMethod = request.method;
|
||||||
const path = request.params.path;
|
const path = request.params.path;
|
||||||
|
|
|
@ -8,26 +8,30 @@ import type {
|
||||||
IRunData,
|
IRunData,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import type {
|
import type {
|
||||||
IResponseCallbackData,
|
IWebhookResponseCallbackData,
|
||||||
IWebhookManager,
|
IWebhookManager,
|
||||||
IWorkflowDb,
|
|
||||||
WebhookAccessControlOptions,
|
WebhookAccessControlOptions,
|
||||||
WebhookRequest,
|
WebhookRequest,
|
||||||
} from '@/Interfaces';
|
} from './webhook.types';
|
||||||
import { Push } from '@/push';
|
import { Push } from '@/push';
|
||||||
import { NodeTypes } from '@/NodeTypes';
|
import { NodeTypes } from '@/NodeTypes';
|
||||||
import * as WebhookHelpers from '@/WebhookHelpers';
|
import * as WebhookHelpers from '@/webhooks/WebhookHelpers';
|
||||||
import { TEST_WEBHOOK_TIMEOUT } from '@/constants';
|
import { TEST_WEBHOOK_TIMEOUT } from '@/constants';
|
||||||
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
||||||
import { WorkflowMissingIdError } from '@/errors/workflow-missing-id.error';
|
import { WorkflowMissingIdError } from '@/errors/workflow-missing-id.error';
|
||||||
import { WebhookNotFoundError } from '@/errors/response-errors/webhook-not-found.error';
|
import { WebhookNotFoundError } from '@/errors/response-errors/webhook-not-found.error';
|
||||||
import * as NodeExecuteFunctions from 'n8n-core';
|
import * as NodeExecuteFunctions from 'n8n-core';
|
||||||
import { removeTrailingSlash } from './utils';
|
import { removeTrailingSlash } from '@/utils';
|
||||||
import type { TestWebhookRegistration } from '@/services/test-webhook-registrations.service';
|
import type { TestWebhookRegistration } from '@/webhooks/test-webhook-registrations.service';
|
||||||
import { TestWebhookRegistrationsService } from '@/services/test-webhook-registrations.service';
|
import { TestWebhookRegistrationsService } from '@/webhooks/test-webhook-registrations.service';
|
||||||
import { OrchestrationService } from '@/services/orchestration.service';
|
import { OrchestrationService } from '@/services/orchestration.service';
|
||||||
import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData';
|
import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData';
|
||||||
|
import type { IWorkflowDb } from '@/Interfaces';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for handling the execution of webhooks of manual executions
|
||||||
|
* that use the [Test URL](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.webhook/#webhook-urls).
|
||||||
|
*/
|
||||||
@Service()
|
@Service()
|
||||||
export class TestWebhooks implements IWebhookManager {
|
export class TestWebhooks implements IWebhookManager {
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -46,7 +50,7 @@ export class TestWebhooks implements IWebhookManager {
|
||||||
async executeWebhook(
|
async executeWebhook(
|
||||||
request: WebhookRequest,
|
request: WebhookRequest,
|
||||||
response: express.Response,
|
response: express.Response,
|
||||||
): Promise<IResponseCallbackData> {
|
): Promise<IWebhookResponseCallbackData> {
|
||||||
const httpMethod = request.method;
|
const httpMethod = request.method;
|
||||||
|
|
||||||
let path = removeTrailingSlash(request.params.path);
|
let path = removeTrailingSlash(request.params.path);
|
||||||
|
@ -117,7 +121,7 @@ export class TestWebhooks implements IWebhookManager {
|
||||||
undefined, // executionId
|
undefined, // executionId
|
||||||
request,
|
request,
|
||||||
response,
|
response,
|
||||||
(error: Error | null, data: IResponseCallbackData) => {
|
(error: Error | null, data: IWebhookResponseCallbackData) => {
|
||||||
if (error !== null) reject(error);
|
if (error !== null) reject(error);
|
||||||
else resolve(data);
|
else resolve(data);
|
||||||
},
|
},
|
|
@ -2,21 +2,25 @@ import { NodeHelpers, Workflow } from 'n8n-workflow';
|
||||||
import { Service } from 'typedi';
|
import { Service } from 'typedi';
|
||||||
import type express from 'express';
|
import type express from 'express';
|
||||||
|
|
||||||
import * as WebhookHelpers from '@/WebhookHelpers';
|
import * as WebhookHelpers from '@/webhooks/WebhookHelpers';
|
||||||
import { NodeTypes } from '@/NodeTypes';
|
import { NodeTypes } from '@/NodeTypes';
|
||||||
import type {
|
import type {
|
||||||
IExecutionResponse,
|
IWebhookResponseCallbackData,
|
||||||
IResponseCallbackData,
|
|
||||||
IWebhookManager,
|
IWebhookManager,
|
||||||
IWorkflowDb,
|
|
||||||
WaitingWebhookRequest,
|
WaitingWebhookRequest,
|
||||||
} from '@/Interfaces';
|
} from './webhook.types';
|
||||||
import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData';
|
import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData';
|
||||||
import { ExecutionRepository } from '@db/repositories/execution.repository';
|
import { ExecutionRepository } from '@db/repositories/execution.repository';
|
||||||
import { Logger } from '@/Logger';
|
import { Logger } from '@/Logger';
|
||||||
import { ConflictError } from './errors/response-errors/conflict.error';
|
import { ConflictError } from '@/errors/response-errors/conflict.error';
|
||||||
import { NotFoundError } from './errors/response-errors/not-found.error';
|
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
||||||
|
import type { IExecutionResponse, IWorkflowDb } from '@/Interfaces';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for handling the execution of webhooks of Wait nodes that use the
|
||||||
|
* [Resume On Webhook Call](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.wait/#on-webhook-call)
|
||||||
|
* feature.
|
||||||
|
*/
|
||||||
@Service()
|
@Service()
|
||||||
export class WaitingWebhooks implements IWebhookManager {
|
export class WaitingWebhooks implements IWebhookManager {
|
||||||
protected includeForms = false;
|
protected includeForms = false;
|
||||||
|
@ -40,7 +44,7 @@ export class WaitingWebhooks implements IWebhookManager {
|
||||||
async executeWebhook(
|
async executeWebhook(
|
||||||
req: WaitingWebhookRequest,
|
req: WaitingWebhookRequest,
|
||||||
res: express.Response,
|
res: express.Response,
|
||||||
): Promise<IResponseCallbackData> {
|
): Promise<IWebhookResponseCallbackData> {
|
||||||
const { path: executionId, suffix } = req.params;
|
const { path: executionId, suffix } = req.params;
|
||||||
|
|
||||||
this.logReceivedWebhook(req.method, executionId);
|
this.logReceivedWebhook(req.method, executionId);
|
|
@ -43,27 +43,25 @@ import {
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
IExecutionDb,
|
IWebhookResponseCallbackData,
|
||||||
IResponseCallbackData,
|
|
||||||
IWebhookManager,
|
IWebhookManager,
|
||||||
IWorkflowDb,
|
|
||||||
IWorkflowExecutionDataProcess,
|
|
||||||
WebhookCORSRequest,
|
WebhookCORSRequest,
|
||||||
WebhookRequest,
|
WebhookRequest,
|
||||||
} from '@/Interfaces';
|
} from './webhook.types';
|
||||||
import * as ResponseHelper from '@/ResponseHelper';
|
import * as ResponseHelper from '@/ResponseHelper';
|
||||||
import * as WorkflowHelpers from '@/WorkflowHelpers';
|
import * as WorkflowHelpers from '@/WorkflowHelpers';
|
||||||
import { WorkflowRunner } from '@/WorkflowRunner';
|
import { WorkflowRunner } from '@/WorkflowRunner';
|
||||||
import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData';
|
import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData';
|
||||||
import { ActiveExecutions } from '@/ActiveExecutions';
|
import { ActiveExecutions } from '@/ActiveExecutions';
|
||||||
import { WorkflowStatisticsService } from '@/services/workflow-statistics.service';
|
import { WorkflowStatisticsService } from '@/services/workflow-statistics.service';
|
||||||
import { OwnershipService } from './services/ownership.service';
|
import { OwnershipService } from '@/services/ownership.service';
|
||||||
import { parseBody } from './middlewares';
|
import { parseBody } from '@/middlewares';
|
||||||
import { Logger } from './Logger';
|
import { Logger } from '@/Logger';
|
||||||
import { NotFoundError } from './errors/response-errors/not-found.error';
|
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
||||||
import { InternalServerError } from './errors/response-errors/internal-server.error';
|
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
|
||||||
import { UnprocessableRequestError } from './errors/response-errors/unprocessable.error';
|
import { UnprocessableRequestError } from '@/errors/response-errors/unprocessable.error';
|
||||||
import type { Project } from './databases/entities/Project';
|
import type { Project } from '@/databases/entities/Project';
|
||||||
|
import type { IExecutionDb, IWorkflowDb, IWorkflowExecutionDataProcess } from '@/Interfaces';
|
||||||
|
|
||||||
export const WEBHOOK_METHODS: IHttpRequestMethods[] = [
|
export const WEBHOOK_METHODS: IHttpRequestMethods[] = [
|
||||||
'DELETE',
|
'DELETE',
|
||||||
|
@ -137,7 +135,7 @@ export const webhookRequestHandler =
|
||||||
return ResponseHelper.sendSuccessResponse(res, {}, true, 204);
|
return ResponseHelper.sendSuccessResponse(res, {}, true, 204);
|
||||||
}
|
}
|
||||||
|
|
||||||
let response;
|
let response: IWebhookResponseCallbackData;
|
||||||
try {
|
try {
|
||||||
response = await webhookManager.executeWebhook(req, res);
|
response = await webhookManager.executeWebhook(req, res);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -228,7 +226,7 @@ export async function executeWebhook(
|
||||||
executionId: string | undefined,
|
executionId: string | undefined,
|
||||||
req: WebhookRequest,
|
req: WebhookRequest,
|
||||||
res: express.Response,
|
res: express.Response,
|
||||||
responseCallback: (error: Error | null, data: IResponseCallbackData) => void,
|
responseCallback: (error: Error | null, data: IWebhookResponseCallbackData) => void,
|
||||||
destinationNode?: string,
|
destinationNode?: string,
|
||||||
): Promise<string | undefined> {
|
): Promise<string | undefined> {
|
||||||
// Get the nodeType to know which responseMode is set
|
// Get the nodeType to know which responseMode is set
|
|
@ -1,20 +1,21 @@
|
||||||
import { mock } from 'jest-mock-extended';
|
import { mock } from 'jest-mock-extended';
|
||||||
import { TestWebhooks } from '@/TestWebhooks';
|
import { TestWebhooks } from '@/webhooks/TestWebhooks';
|
||||||
import { WebhookNotFoundError } from '@/errors/response-errors/webhook-not-found.error';
|
import { WebhookNotFoundError } from '@/errors/response-errors/webhook-not-found.error';
|
||||||
import { v4 as uuid } from 'uuid';
|
import { v4 as uuid } from 'uuid';
|
||||||
import { generateNanoId } from '@/databases/utils/generators';
|
import { generateNanoId } from '@/databases/utils/generators';
|
||||||
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
||||||
import * as WebhookHelpers from '@/WebhookHelpers';
|
import * as WebhookHelpers from '@/webhooks/WebhookHelpers';
|
||||||
import type * as express from 'express';
|
import type * as express from 'express';
|
||||||
|
|
||||||
import type { IWorkflowDb, WebhookRequest } from '@/Interfaces';
|
import type { IWorkflowDb } from '@/Interfaces';
|
||||||
import type { IWebhookData, IWorkflowExecuteAdditionalData, Workflow } from 'n8n-workflow';
|
import type { IWebhookData, IWorkflowExecuteAdditionalData, Workflow } from 'n8n-workflow';
|
||||||
import type {
|
import type {
|
||||||
TestWebhookRegistrationsService,
|
TestWebhookRegistrationsService,
|
||||||
TestWebhookRegistration,
|
TestWebhookRegistration,
|
||||||
} from '@/services/test-webhook-registrations.service';
|
} from '@/webhooks/test-webhook-registrations.service';
|
||||||
|
|
||||||
import * as AdditionalData from '@/WorkflowExecuteAdditionalData';
|
import * as AdditionalData from '@/WorkflowExecuteAdditionalData';
|
||||||
|
import type { WebhookRequest } from '@/webhooks/webhook.types';
|
||||||
|
|
||||||
jest.mock('@/WorkflowExecuteAdditionalData');
|
jest.mock('@/WorkflowExecuteAdditionalData');
|
||||||
|
|
|
@ -3,8 +3,8 @@ import { mock } from 'jest-mock-extended';
|
||||||
import { randomString } from 'n8n-workflow';
|
import { randomString } from 'n8n-workflow';
|
||||||
import type { IHttpRequestMethods } from 'n8n-workflow';
|
import type { IHttpRequestMethods } from 'n8n-workflow';
|
||||||
|
|
||||||
import type { IWebhookManager, WebhookCORSRequest, WebhookRequest } from '@/Interfaces';
|
import type { IWebhookManager, WebhookCORSRequest, WebhookRequest } from '@/webhooks/webhook.types';
|
||||||
import { webhookRequestHandler } from '@/WebhookHelpers';
|
import { webhookRequestHandler } from '@/webhooks/WebhookHelpers';
|
||||||
|
|
||||||
describe('WebhookHelpers', () => {
|
describe('WebhookHelpers', () => {
|
||||||
describe('webhookRequestHandler', () => {
|
describe('webhookRequestHandler', () => {
|
|
@ -1,7 +1,7 @@
|
||||||
import type { CacheService } from '@/services/cache/cache.service';
|
import type { CacheService } from '@/services/cache/cache.service';
|
||||||
import type { OrchestrationService } from '@/services/orchestration.service';
|
import type { OrchestrationService } from '@/services/orchestration.service';
|
||||||
import type { TestWebhookRegistration } from '@/services/test-webhook-registrations.service';
|
import type { TestWebhookRegistration } from '@/webhooks/test-webhook-registrations.service';
|
||||||
import { TestWebhookRegistrationsService } from '@/services/test-webhook-registrations.service';
|
import { TestWebhookRegistrationsService } from '@/webhooks/test-webhook-registrations.service';
|
||||||
import { mock } from 'jest-mock-extended';
|
import { mock } from 'jest-mock-extended';
|
||||||
|
|
||||||
describe('TestWebhookRegistrationsService', () => {
|
describe('TestWebhookRegistrationsService', () => {
|
|
@ -1,10 +1,11 @@
|
||||||
import { mock } from 'jest-mock-extended';
|
import { mock } from 'jest-mock-extended';
|
||||||
import { WaitingWebhooks } from '@/WaitingWebhooks';
|
import { WaitingWebhooks } from '@/webhooks/WaitingWebhooks';
|
||||||
import { ConflictError } from '@/errors/response-errors/conflict.error';
|
import { ConflictError } from '@/errors/response-errors/conflict.error';
|
||||||
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
||||||
import type { IExecutionResponse, WaitingWebhookRequest } from '@/Interfaces';
|
import type { IExecutionResponse } from '@/Interfaces';
|
||||||
import type express from 'express';
|
import type express from 'express';
|
||||||
import type { ExecutionRepository } from '@/databases/repositories/execution.repository';
|
import type { ExecutionRepository } from '@/databases/repositories/execution.repository';
|
||||||
|
import type { WaitingWebhookRequest } from '@/webhooks/webhook.types';
|
||||||
|
|
||||||
describe('WaitingWebhooks', () => {
|
describe('WaitingWebhooks', () => {
|
||||||
const executionRepository = mock<ExecutionRepository>();
|
const executionRepository = mock<ExecutionRepository>();
|
|
@ -2,7 +2,7 @@ import { v4 as uuid } from 'uuid';
|
||||||
import config from '@/config';
|
import config from '@/config';
|
||||||
import { WebhookRepository } from '@db/repositories/webhook.repository';
|
import { WebhookRepository } from '@db/repositories/webhook.repository';
|
||||||
import { CacheService } from '@/services/cache/cache.service';
|
import { CacheService } from '@/services/cache/cache.service';
|
||||||
import { WebhookService } from '@/services/webhook.service';
|
import { WebhookService } from '@/webhooks/webhook.service';
|
||||||
import { WebhookEntity } from '@db/entities/WebhookEntity';
|
import { WebhookEntity } from '@db/entities/WebhookEntity';
|
||||||
import { mockInstance } from '@test/mocking';
|
import { mockInstance } from '@test/mocking';
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { CacheService } from '@/services/cache/cache.service';
|
||||||
import type { IWebhookData } from 'n8n-workflow';
|
import type { IWebhookData } from 'n8n-workflow';
|
||||||
import type { IWorkflowDb } from '@/Interfaces';
|
import type { IWorkflowDb } from '@/Interfaces';
|
||||||
import { TEST_WEBHOOK_TIMEOUT, TEST_WEBHOOK_TIMEOUT_BUFFER } from '@/constants';
|
import { TEST_WEBHOOK_TIMEOUT, TEST_WEBHOOK_TIMEOUT_BUFFER } from '@/constants';
|
||||||
import { OrchestrationService } from './orchestration.service';
|
import { OrchestrationService } from '@/services/orchestration.service';
|
||||||
|
|
||||||
export type TestWebhookRegistration = {
|
export type TestWebhookRegistration = {
|
||||||
pushRef?: string;
|
pushRef?: string;
|
37
packages/cli/src/webhooks/webhook.types.ts
Normal file
37
packages/cli/src/webhooks/webhook.types.ts
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import type { Request, Response } from 'express';
|
||||||
|
import type { IDataObject, IHttpRequestMethods } from 'n8n-workflow';
|
||||||
|
|
||||||
|
export type WebhookCORSRequest = Request & { method: 'OPTIONS' };
|
||||||
|
|
||||||
|
export type WebhookRequest = Request<{ path: string }> & {
|
||||||
|
method: IHttpRequestMethods;
|
||||||
|
params: Record<string, string>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type WaitingWebhookRequest = WebhookRequest & {
|
||||||
|
params: WebhookRequest['path'] & { suffix?: string };
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface WebhookAccessControlOptions {
|
||||||
|
allowedOrigins?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IWebhookManager {
|
||||||
|
/** Gets all request methods associated with a webhook path*/
|
||||||
|
getWebhookMethods?: (path: string) => Promise<IHttpRequestMethods[]>;
|
||||||
|
|
||||||
|
/** Find the CORS options matching a path and method */
|
||||||
|
findAccessControlOptions?: (
|
||||||
|
path: string,
|
||||||
|
httpMethod: IHttpRequestMethods,
|
||||||
|
) => Promise<WebhookAccessControlOptions | undefined>;
|
||||||
|
|
||||||
|
executeWebhook(req: WebhookRequest, res: Response): Promise<IWebhookResponseCallbackData>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IWebhookResponseCallbackData {
|
||||||
|
data?: IDataObject | IDataObject[];
|
||||||
|
headers?: object;
|
||||||
|
noWebhookResponse?: boolean;
|
||||||
|
responseCode?: number;
|
||||||
|
}
|
|
@ -30,7 +30,7 @@ import type {
|
||||||
import { NodeTypes } from '@/NodeTypes';
|
import { NodeTypes } from '@/NodeTypes';
|
||||||
import { WorkflowRunner } from '@/WorkflowRunner';
|
import { WorkflowRunner } from '@/WorkflowRunner';
|
||||||
import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData';
|
import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData';
|
||||||
import { TestWebhooks } from '@/TestWebhooks';
|
import { TestWebhooks } from '@/webhooks/TestWebhooks';
|
||||||
import { Logger } from '@/Logger';
|
import { Logger } from '@/Logger';
|
||||||
import type { Project } from '@/databases/entities/Project';
|
import type { Project } from '@/databases/entities/Project';
|
||||||
import { GlobalConfig } from '@n8n/config';
|
import { GlobalConfig } from '@n8n/config';
|
||||||
|
|
|
@ -8,8 +8,8 @@ import { ActiveWorkflowManager } from '@/ActiveWorkflowManager';
|
||||||
import { ExternalHooks } from '@/ExternalHooks';
|
import { ExternalHooks } from '@/ExternalHooks';
|
||||||
import { Push } from '@/push';
|
import { Push } from '@/push';
|
||||||
import { SecretsHelper } from '@/SecretsHelpers';
|
import { SecretsHelper } from '@/SecretsHelpers';
|
||||||
import { WebhookService } from '@/services/webhook.service';
|
import { WebhookService } from '@/webhooks/webhook.service';
|
||||||
import * as WebhookHelpers from '@/WebhookHelpers';
|
import * as WebhookHelpers from '@/webhooks/WebhookHelpers';
|
||||||
import * as AdditionalData from '@/WorkflowExecuteAdditionalData';
|
import * as AdditionalData from '@/WorkflowExecuteAdditionalData';
|
||||||
import type { WebhookEntity } from '@db/entities/WebhookEntity';
|
import type { WebhookEntity } from '@db/entities/WebhookEntity';
|
||||||
import { NodeTypes } from '@/NodeTypes';
|
import { NodeTypes } from '@/NodeTypes';
|
||||||
|
|
|
@ -3,13 +3,13 @@ import { agent as testAgent } from 'supertest';
|
||||||
import { mock } from 'jest-mock-extended';
|
import { mock } from 'jest-mock-extended';
|
||||||
|
|
||||||
import { AbstractServer } from '@/AbstractServer';
|
import { AbstractServer } from '@/AbstractServer';
|
||||||
import { ActiveWebhooks } from '@/ActiveWebhooks';
|
import { ActiveWebhooks } from '@/webhooks/ActiveWebhooks';
|
||||||
import { ExternalHooks } from '@/ExternalHooks';
|
import { ExternalHooks } from '@/ExternalHooks';
|
||||||
import { InternalHooks } from '@/InternalHooks';
|
import { InternalHooks } from '@/InternalHooks';
|
||||||
import { TestWebhooks } from '@/TestWebhooks';
|
import { TestWebhooks } from '@/webhooks/TestWebhooks';
|
||||||
import { WaitingWebhooks } from '@/WaitingWebhooks';
|
import { WaitingWebhooks } from '@/webhooks/WaitingWebhooks';
|
||||||
import { WaitingForms } from '@/WaitingForms';
|
import { WaitingForms } from '@/WaitingForms';
|
||||||
import type { IResponseCallbackData } from '@/Interfaces';
|
import type { IWebhookResponseCallbackData } from '@/webhooks/webhook.types';
|
||||||
|
|
||||||
import { mockInstance } from '@test/mocking';
|
import { mockInstance } from '@test/mocking';
|
||||||
import { GlobalConfig } from '@n8n/config';
|
import { GlobalConfig } from '@n8n/config';
|
||||||
|
@ -80,7 +80,7 @@ describe('WebhookServer', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const mockResponse = (data = {}, headers = {}, status = 200) => {
|
const mockResponse = (data = {}, headers = {}, status = 200) => {
|
||||||
const response = mock<IResponseCallbackData>();
|
const response = mock<IWebhookResponseCallbackData>();
|
||||||
response.responseCode = status;
|
response.responseCode = status;
|
||||||
response.data = data;
|
response.data = data;
|
||||||
response.headers = headers;
|
response.headers = headers;
|
||||||
|
|
Loading…
Reference in a new issue