mirror of
https://github.com/n8n-io/n8n.git
synced 2026-10-17 05:29:44 +02:00
refactor(core): Extract webhook additional data setup (#39673)
This commit is contained in:
parent
53dc251508
commit
3ec310db40
|
|
@ -753,93 +753,38 @@ function toWebhookUser(user: IUser): IUser {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a webhook
|
||||
*/
|
||||
// eslint-disable-next-line complexity
|
||||
export async function executeWebhook(
|
||||
workflow: Workflow,
|
||||
webhookData: IWebhookData,
|
||||
workflowData: IWorkflowBase,
|
||||
workflowStartNode: INode,
|
||||
executionMode: WorkflowExecuteMode,
|
||||
pushRef: string | undefined,
|
||||
runExecutionData: IRunExecutionData | undefined,
|
||||
executionId: string | undefined,
|
||||
req: WebhookRequest,
|
||||
res: express.Response,
|
||||
responseCallback: WebhookResponseCallback,
|
||||
destinationNode?: IDestinationNode,
|
||||
options?: {
|
||||
/**
|
||||
* Identity of the builder who registered this test webhook, for a manual run that
|
||||
* had to wait for a webhook and so never reached the point where a manual
|
||||
* execution normally picks its identity up from the auth cookie. Only a fallback:
|
||||
* a node that establishes its own carrier below still wins.
|
||||
*/
|
||||
encryptedRunnerIdentity?: string;
|
||||
},
|
||||
): Promise<string | undefined> {
|
||||
const responder = new WebhookResponder(responseCallback);
|
||||
|
||||
// Get the nodeType to know which responseMode is set
|
||||
const nodeType = workflow.nodeTypes.getByNameAndVersion(
|
||||
workflowStartNode.type,
|
||||
workflowStartNode.typeVersion,
|
||||
);
|
||||
|
||||
const additionalKeys: IWorkflowDataProxyAdditionalKeys = {
|
||||
$executionId: executionId,
|
||||
};
|
||||
|
||||
const context = new WebhookExecutionContext(
|
||||
workflow,
|
||||
workflowStartNode,
|
||||
webhookData,
|
||||
executionMode,
|
||||
additionalKeys,
|
||||
);
|
||||
|
||||
let project: Project;
|
||||
try {
|
||||
project = await Container.get(OwnershipService).getWorkflowProjectCached(workflowData.id);
|
||||
} catch {
|
||||
throw new NotFoundError('Cannot find workflow');
|
||||
}
|
||||
|
||||
// Prepare everything that is needed to run the workflow
|
||||
const additionalData = await WorkflowExecuteAdditionalData.getBase({
|
||||
projectId: project?.id,
|
||||
});
|
||||
async function prepareWebhookAdditionalData({
|
||||
workflow,
|
||||
workflowStartNode,
|
||||
executionMode,
|
||||
executionId,
|
||||
projectId,
|
||||
req,
|
||||
res,
|
||||
encryptedRunnerIdentity,
|
||||
getRunExecutionData,
|
||||
}: {
|
||||
workflow: Workflow;
|
||||
workflowStartNode: INode;
|
||||
executionMode: WorkflowExecuteMode;
|
||||
executionId: string | undefined;
|
||||
projectId: string;
|
||||
req: WebhookRequest;
|
||||
res: express.Response;
|
||||
encryptedRunnerIdentity?: string;
|
||||
getRunExecutionData: () => IRunExecutionData | undefined;
|
||||
}): Promise<IWorkflowExecuteAdditionalData> {
|
||||
const additionalData = await WorkflowExecuteAdditionalData.getBase({ projectId });
|
||||
|
||||
// Guarded: an absent carrier must not clobber one set elsewhere.
|
||||
if (options?.encryptedRunnerIdentity) {
|
||||
additionalData.encryptedRunnerIdentity = options.encryptedRunnerIdentity;
|
||||
if (encryptedRunnerIdentity) {
|
||||
additionalData.encryptedRunnerIdentity = encryptedRunnerIdentity;
|
||||
}
|
||||
|
||||
if (executionId) {
|
||||
additionalData.executionId = executionId;
|
||||
}
|
||||
|
||||
const {
|
||||
responseMode,
|
||||
responseCode,
|
||||
responseData,
|
||||
checkAllMainOutputs,
|
||||
responsePropertyName,
|
||||
responseContentType,
|
||||
responseBinaryPropertyName,
|
||||
} = evaluateResponseOptions(context, req);
|
||||
|
||||
if (!SUPPORTED_RESPONSE_MODES.has(responseMode)) {
|
||||
// If the mode is not known we error. Is probably best like that instead of using
|
||||
// the default that people know as early as possible (probably already testing phase)
|
||||
// that something does not resolve properly.
|
||||
const errorMessage = `The response mode '${responseMode}' is not valid!`;
|
||||
responder.respondWithError(new UnexpectedError(errorMessage));
|
||||
throw new InternalServerError(errorMessage);
|
||||
}
|
||||
|
||||
// Add the Response and Request so that this data can be accessed in the node
|
||||
additionalData.httpRequest = req;
|
||||
additionalData.httpResponse = res;
|
||||
|
|
@ -907,6 +852,7 @@ export async function executeWebhook(
|
|||
additionalData.encryptedRunnerIdentity = await Container.get(
|
||||
ExecutionContextService,
|
||||
).buildTriggerIdentityCredentials(token, resource, grant, subject);
|
||||
const runExecutionData = getRunExecutionData();
|
||||
if (runExecutionData) {
|
||||
await establishExecutionContext(workflow, runExecutionData, additionalData, executionMode);
|
||||
}
|
||||
|
|
@ -923,6 +869,7 @@ export async function executeWebhook(
|
|||
if (!credentialCheckProxy || !workflow.id) {
|
||||
return undefined;
|
||||
}
|
||||
const runExecutionData = getRunExecutionData();
|
||||
const executionContext =
|
||||
runExecutionData?.executionData?.runtimeData ??
|
||||
(additionalData.encryptedRunnerIdentity
|
||||
|
|
@ -958,6 +905,95 @@ export async function executeWebhook(
|
|||
});
|
||||
};
|
||||
|
||||
return additionalData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a webhook
|
||||
*/
|
||||
// eslint-disable-next-line complexity
|
||||
export async function executeWebhook(
|
||||
workflow: Workflow,
|
||||
webhookData: IWebhookData,
|
||||
workflowData: IWorkflowBase,
|
||||
workflowStartNode: INode,
|
||||
executionMode: WorkflowExecuteMode,
|
||||
pushRef: string | undefined,
|
||||
runExecutionData: IRunExecutionData | undefined,
|
||||
executionId: string | undefined,
|
||||
req: WebhookRequest,
|
||||
res: express.Response,
|
||||
responseCallback: WebhookResponseCallback,
|
||||
destinationNode?: IDestinationNode,
|
||||
options?: {
|
||||
/**
|
||||
* Identity of the builder who registered this test webhook, for a manual run that
|
||||
* had to wait for a webhook and so never reached the point where a manual
|
||||
* execution normally picks its identity up from the auth cookie. Only a fallback:
|
||||
* a node that establishes its own carrier below still wins.
|
||||
*/
|
||||
encryptedRunnerIdentity?: string;
|
||||
},
|
||||
): Promise<string | undefined> {
|
||||
const responder = new WebhookResponder(responseCallback);
|
||||
|
||||
// Get the nodeType to know which responseMode is set
|
||||
const nodeType = workflow.nodeTypes.getByNameAndVersion(
|
||||
workflowStartNode.type,
|
||||
workflowStartNode.typeVersion,
|
||||
);
|
||||
|
||||
const additionalKeys: IWorkflowDataProxyAdditionalKeys = {
|
||||
$executionId: executionId,
|
||||
};
|
||||
|
||||
const context = new WebhookExecutionContext(
|
||||
workflow,
|
||||
workflowStartNode,
|
||||
webhookData,
|
||||
executionMode,
|
||||
additionalKeys,
|
||||
);
|
||||
|
||||
let project: Project;
|
||||
try {
|
||||
project = await Container.get(OwnershipService).getWorkflowProjectCached(workflowData.id);
|
||||
} catch {
|
||||
throw new NotFoundError('Cannot find workflow');
|
||||
}
|
||||
|
||||
// Prepare everything that is needed to run the workflow
|
||||
const additionalData = await prepareWebhookAdditionalData({
|
||||
workflow,
|
||||
workflowStartNode,
|
||||
executionMode,
|
||||
executionId,
|
||||
projectId: project?.id,
|
||||
req,
|
||||
res,
|
||||
encryptedRunnerIdentity: options?.encryptedRunnerIdentity,
|
||||
getRunExecutionData: () => runExecutionData,
|
||||
});
|
||||
|
||||
const {
|
||||
responseMode,
|
||||
responseCode,
|
||||
responseData,
|
||||
checkAllMainOutputs,
|
||||
responsePropertyName,
|
||||
responseContentType,
|
||||
responseBinaryPropertyName,
|
||||
} = evaluateResponseOptions(context, req);
|
||||
|
||||
if (!SUPPORTED_RESPONSE_MODES.has(responseMode)) {
|
||||
// If the mode is not known we error. Is probably best like that instead of using
|
||||
// the default that people know as early as possible (probably already testing phase)
|
||||
// that something does not resolve properly.
|
||||
const errorMessage = `The response mode '${responseMode}' is not valid!`;
|
||||
responder.respondWithError(new UnexpectedError(errorMessage));
|
||||
throw new InternalServerError(errorMessage);
|
||||
}
|
||||
|
||||
/** Whether this run goes to the engine v2 data plane instead of the v1 path. */
|
||||
let routesToEngineV2 = false;
|
||||
let pendingEngineV2Response: PendingWebhookResponse | undefined;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user