n8n
Version:
n8n Workflow Automation Tool
374 lines • 16.9 kB
JavaScript
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
;