UNPKG

n8n

Version:

n8n Workflow Automation Tool

374 lines 16.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getWebhookBaseUrl = exports.executeWebhook = exports.getWorkflowWebhooksBasic = exports.encodeWebhookResponse = exports.decodeWebhookResponse = exports.getWorkflowWebhooks = void 0; const lodash_1 = require("lodash"); const n8n_core_1 = require("n8n-core"); const n8n_workflow_1 = require("n8n-workflow"); const _1 = require("."); const ActiveExecutions = require("./ActiveExecutions"); const activeExecutions = ActiveExecutions.getInstance(); function getWorkflowWebhooks(workflow, additionalData, destinationNode, ignoreRestartWehbooks = false) { const returnData = []; let parentNodes; if (destinationNode !== undefined) { parentNodes = workflow.getParentNodes(destinationNode); parentNodes.push(destinationNode); } for (const node of Object.values(workflow.nodes)) { if (parentNodes !== undefined && !parentNodes.includes(node.name)) { continue; } returnData.push.apply(returnData, n8n_workflow_1.NodeHelpers.getNodeWebhooks(workflow, node, additionalData, ignoreRestartWehbooks)); } return returnData; } exports.getWorkflowWebhooks = getWorkflowWebhooks; function decodeWebhookResponse(response) { if (typeof response === 'object' && typeof response.body === 'object' && response.body['__@N8nEncodedBuffer@__']) { response.body = Buffer.from(response.body['__@N8nEncodedBuffer@__'], n8n_core_1.BINARY_ENCODING); } return response; } exports.decodeWebhookResponse = decodeWebhookResponse; function encodeWebhookResponse(response) { if (typeof response === 'object' && Buffer.isBuffer(response.body)) { response.body = { '__@N8nEncodedBuffer@__': response.body.toString(n8n_core_1.BINARY_ENCODING), }; } return response; } exports.encodeWebhookResponse = encodeWebhookResponse; function getWorkflowWebhooksBasic(workflow) { const returnData = []; for (const node of Object.values(workflow.nodes)) { returnData.push.apply(returnData, n8n_workflow_1.NodeHelpers.getNodeWebhooksBasic(workflow, node)); } return returnData; } exports.getWorkflowWebhooksBasic = getWorkflowWebhooksBasic; async function executeWebhook(workflow, webhookData, workflowData, workflowStartNode, executionMode, sessionId, runExecutionData, executionId, req, res, responseCallback) { const nodeType = workflow.nodeTypes.getByNameAndVersion(workflowStartNode.type, workflowStartNode.typeVersion); if (nodeType === undefined) { const errorMessage = `The type of the webhook node "${workflowStartNode.name}" is not known.`; responseCallback(new Error(errorMessage), {}); throw new _1.ResponseHelper.ResponseError(errorMessage, 500, 500); } const additionalKeys = { $executionId: executionId, }; const responseMode = workflow.expression.getSimpleParameterValue(workflowStartNode, webhookData.webhookDescription.responseMode, executionMode, additionalKeys, 'onReceived'); const responseCode = workflow.expression.getSimpleParameterValue(workflowStartNode, webhookData.webhookDescription.responseCode, executionMode, additionalKeys, 200); if (!['onReceived', 'lastNode', 'responseNode'].includes(responseMode)) { const errorMessage = `The response mode ${responseMode} is not valid!`; responseCallback(new Error(errorMessage), {}); throw new _1.ResponseHelper.ResponseError(errorMessage, 500, 500); } const additionalData = await _1.WorkflowExecuteAdditionalData.getBase(); additionalData.httpRequest = req; additionalData.httpResponse = res; let didSendResponse = false; let runExecutionDataMerge = {}; try { let webhookResultData; try { webhookResultData = await workflow.runWebhook(webhookData, workflowStartNode, additionalData, n8n_core_1.NodeExecuteFunctions, executionMode); } catch (err) { const errorMessage = 'Workflow Webhook Error: Workflow could not be started!'; responseCallback(new Error(errorMessage), {}); didSendResponse = true; runExecutionDataMerge = { resultData: { runData: {}, lastNodeExecuted: workflowStartNode.name, error: Object.assign(Object.assign({}, err), { message: err.message, stack: err.stack }), }, }; webhookResultData = { noWebhookResponse: true, workflowData: [[{ json: {} }]], }; } await _1.WorkflowHelpers.saveStaticData(workflow); const additionalKeys = { $executionId: executionId, }; if (webhookData.webhookDescription.responseHeaders !== undefined) { const responseHeaders = workflow.expression.getComplexParameterValue(workflowStartNode, webhookData.webhookDescription.responseHeaders, executionMode, additionalKeys, undefined); if (responseHeaders !== undefined && responseHeaders.entries !== undefined) { for (const item of responseHeaders.entries) { res.setHeader(item.name, item.value); } } } if (webhookResultData.noWebhookResponse === true && !didSendResponse) { responseCallback(null, { noWebhookResponse: true, }); didSendResponse = true; } if (webhookResultData.workflowData === undefined) { if (webhookResultData.webhookResponse !== undefined) { if (!didSendResponse) { responseCallback(null, { data: webhookResultData.webhookResponse, responseCode, }); didSendResponse = true; } } else { if (!didSendResponse) { responseCallback(null, { data: { message: 'Webhook call got received.', }, responseCode, }); didSendResponse = true; } } return; } if (responseMode === 'onReceived' && !didSendResponse) { if (webhookResultData.webhookResponse !== undefined) { responseCallback(null, { data: webhookResultData.webhookResponse, responseCode, }); } else { responseCallback(null, { data: { message: 'Workflow got started.', }, responseCode, }); } didSendResponse = true; } const nodeExecutionStack = []; nodeExecutionStack.push({ node: workflowStartNode, data: { main: webhookResultData.workflowData, }, }); runExecutionData = runExecutionData || { startData: {}, resultData: { runData: {}, }, executionData: { contextData: {}, nodeExecutionStack, waitingExecution: {}, }, }; if (executionId !== undefined) { runExecutionData.executionData.nodeExecutionStack[0].data.main = webhookResultData.workflowData; } if (Object.keys(runExecutionDataMerge).length !== 0) { Object.assign(runExecutionData, runExecutionDataMerge); } const runData = { executionMode, executionData: runExecutionData, sessionId, workflowData, }; let responsePromise; if (responseMode === 'responseNode') { responsePromise = await n8n_workflow_1.createDeferredPromise(); responsePromise .promise() .then((response) => { if (didSendResponse) { return; } if (Buffer.isBuffer(response.body)) { res.header(response.headers); res.end(response.body); responseCallback(null, { noWebhookResponse: true, }); } else { responseCallback(null, { data: response.body, headers: response.headers, responseCode: response.statusCode, }); } didSendResponse = true; }) .catch(async (error) => { n8n_workflow_1.LoggerProxy.error(`Error with Webhook-Response for execution "${executionId}": "${error.message}"`, { executionId, workflowId: workflow.id }); }); } const workflowRunner = new _1.WorkflowRunner(); executionId = await workflowRunner.run(runData, true, !didSendResponse, executionId, responsePromise); n8n_workflow_1.LoggerProxy.verbose(`Started execution of workflow "${workflow.name}" from webhook with execution ID ${executionId}`, { executionId }); const executePromise = activeExecutions.getPostExecutePromise(executionId); executePromise .then((data) => { if (data === undefined) { if (!didSendResponse) { responseCallback(null, { data: { message: 'Workflow did execute sucessfully but no data got returned.', }, responseCode, }); didSendResponse = true; } return undefined; } const returnData = _1.WorkflowHelpers.getDataLastExecutedNodeData(data); if (data.data.resultData.error || (returnData === null || returnData === void 0 ? void 0 : returnData.error) !== undefined) { if (!didSendResponse) { responseCallback(null, { data: { message: 'Workflow did error.', }, responseCode: 500, }); } didSendResponse = true; return data; } if (responseMode === 'responseNode') { if (!didSendResponse) { responseCallback(null, { data: { message: 'Workflow executed sucessfully.', }, responseCode, }); didSendResponse = true; } return undefined; } if (returnData === undefined) { if (!didSendResponse) { responseCallback(null, { data: { message: 'Workflow did execute sucessfully but the last node did not return any data.', }, responseCode, }); } didSendResponse = true; return data; } const additionalKeys = { $executionId: executionId, }; const responseData = workflow.expression.getSimpleParameterValue(workflowStartNode, webhookData.webhookDescription.responseData, executionMode, additionalKeys, 'firstEntryJson'); if (!didSendResponse) { let data; if (responseData === 'firstEntryJson') { if (returnData.data.main[0][0] === undefined) { responseCallback(new Error('No item to return got found.'), {}); didSendResponse = true; } data = returnData.data.main[0][0].json; const responsePropertyName = workflow.expression.getSimpleParameterValue(workflowStartNode, webhookData.webhookDescription.responsePropertyName, executionMode, additionalKeys, undefined); if (responsePropertyName !== undefined) { data = lodash_1.get(data, responsePropertyName); } const responseContentType = workflow.expression.getSimpleParameterValue(workflowStartNode, webhookData.webhookDescription.responseContentType, executionMode, additionalKeys, undefined); if (responseContentType !== undefined) { res.setHeader('Content-Type', responseContentType); if (data !== null && data !== undefined && ['Buffer', 'String'].includes(data.constructor.name)) { res.end(data); } else { res.end(JSON.stringify(data)); } responseCallback(null, { noWebhookResponse: true, }); didSendResponse = true; } } else if (responseData === 'firstEntryBinary') { data = returnData.data.main[0][0]; if (data === undefined) { responseCallback(new Error('No item to return got found.'), {}); didSendResponse = true; } if (data.binary === undefined) { responseCallback(new Error('No binary data to return got found.'), {}); didSendResponse = true; } const responseBinaryPropertyName = workflow.expression.getSimpleParameterValue(workflowStartNode, webhookData.webhookDescription.responseBinaryPropertyName, executionMode, additionalKeys, 'data'); if (responseBinaryPropertyName === undefined && !didSendResponse) { responseCallback(new Error('No "responseBinaryPropertyName" is set.'), {}); didSendResponse = true; } const binaryData = data.binary[responseBinaryPropertyName]; if (binaryData === undefined && !didSendResponse) { responseCallback(new Error(`The binary property "${responseBinaryPropertyName}" which should be returned does not exist.`), {}); didSendResponse = true; } if (!didSendResponse) { res.setHeader('Content-Type', binaryData.mimeType); res.end(Buffer.from(binaryData.data, n8n_core_1.BINARY_ENCODING)); responseCallback(null, { noWebhookResponse: true, }); } } else { data = []; for (const entry of returnData.data.main[0]) { data.push(entry.json); } } if (!didSendResponse) { responseCallback(null, { data, responseCode, }); } } didSendResponse = true; return data; }) .catch((e) => { if (!didSendResponse) { responseCallback(new Error('There was a problem executing the workflow.'), {}); } throw new _1.ResponseHelper.ResponseError(e.message, 500, 500); }); return executionId; } catch (e) { if (!didSendResponse) { responseCallback(new Error('There was a problem executing the workflow.'), {}); } throw new _1.ResponseHelper.ResponseError(e.message, 500, 500); } } exports.executeWebhook = executeWebhook; function getWebhookBaseUrl() { let urlBaseWebhook = _1.GenericHelpers.getBaseUrl(); if (process.env.WEBHOOK_TUNNEL_URL !== undefined || process.env.WEBHOOK_URL !== undefined) { urlBaseWebhook = process.env.WEBHOOK_TUNNEL_URL || process.env.WEBHOOK_URL; } if (!urlBaseWebhook.endsWith('/')) { urlBaseWebhook += '/'; } return urlBaseWebhook; } exports.getWebhookBaseUrl = getWebhookBaseUrl; //# sourceMappingURL=WebhookHelpers.js.map