diff --git a/packages/core/src/NodeExecuteFunctions.ts b/packages/core/src/NodeExecuteFunctions.ts index 731f466f66..212f8140b1 100644 --- a/packages/core/src/NodeExecuteFunctions.ts +++ b/packages/core/src/NodeExecuteFunctions.ts @@ -249,6 +249,19 @@ export function getNodeParameter(workflow: Workflow, runExecutionData: IRunExecu +/** + * Returns if execution should be continued even if there was an error. + * + * @export + * @param {INode} node + * @returns {boolean} + */ +export function continueOnFail(node: INode): boolean { + return get(node, 'continueOnFail', false); +} + + + /** * Returns the webhook URL of the webhook with the given name * @@ -474,6 +487,9 @@ export function getExecuteTriggerFunctions(workflow: Workflow, node: INode, addi export function getExecuteFunctions(workflow: Workflow, runExecutionData: IRunExecutionData, runIndex: number, connectionInputData: INodeExecutionData[], inputData: ITaskDataConnections, node: INode, additionalData: IWorkflowExecuteAdditionalData, mode: WorkflowExecuteMode): IExecuteFunctions { return ((workflow, runExecutionData, connectionInputData, inputData, node) => { return { + continueOnFail: () => { + return continueOnFail(node); + }, async executeWorkflow(workflowInfo: IExecuteWorkflowInfo, inputData?: INodeExecutionData[]): Promise { // tslint:disable-line:no-any return additionalData.executeWorkflow(workflowInfo, additionalData, inputData); }, @@ -559,6 +575,9 @@ export function getExecuteFunctions(workflow: Workflow, runExecutionData: IRunEx export function getExecuteSingleFunctions(workflow: Workflow, runExecutionData: IRunExecutionData, runIndex: number, connectionInputData: INodeExecutionData[], inputData: ITaskDataConnections, node: INode, itemIndex: number, additionalData: IWorkflowExecuteAdditionalData, mode: WorkflowExecuteMode): IExecuteSingleFunctions { return ((workflow, runExecutionData, connectionInputData, inputData, node, itemIndex) => { return { + continueOnFail: () => { + return continueOnFail(node); + }, getContext(type: string): IContextObject { return NodeHelpers.getContext(runExecutionData, type, node); }, diff --git a/packages/nodes-base/nodes/HttpRequest.node.ts b/packages/nodes-base/nodes/HttpRequest.node.ts index ccec53a90b..46334110f1 100644 --- a/packages/nodes-base/nodes/HttpRequest.node.ts +++ b/packages/nodes-base/nodes/HttpRequest.node.ts @@ -586,9 +586,10 @@ export class HttpRequest implements INodeType { }, }; + let response: any; // tslint:disable-line:no-any const returnItems: INodeExecutionData[] = []; for (let itemIndex = 0; itemIndex < items.length; itemIndex++) { - const options = this.getNodeParameter('options', 0, {}) as IDataObject; + const options = this.getNodeParameter('options', itemIndex, {}) as IDataObject; const url = this.getNodeParameter('url', itemIndex) as string; const fullResponse = !!options.fullResponse as boolean; @@ -741,8 +742,17 @@ export class HttpRequest implements INodeType { requestOptions.json = true; } - // Now that the options are all set make the actual http request - const response = await this.helpers.request(requestOptions); + try { + // Now that the options are all set make the actual http request + response = await this.helpers.request(requestOptions); + } catch (error) { + if (this.continueOnFail() === true) { + returnItems.push({ json: { error } }); + continue; + } + + throw error; + } if (responseFormat === 'file') { const dataPropertyName = this.getNodeParameter('dataPropertyName', 0) as string; diff --git a/packages/nodes-base/nodes/NextCloud/NextCloud.node.ts b/packages/nodes-base/nodes/NextCloud/NextCloud.node.ts index ada88cd067..309f53ceae 100644 --- a/packages/nodes-base/nodes/NextCloud/NextCloud.node.ts +++ b/packages/nodes-base/nodes/NextCloud/NextCloud.node.ts @@ -457,12 +457,12 @@ export class NextCloud implements INodeType { let endpoint = ''; let requestMethod = ''; + let responseData: any; // tslint:disable-line:no-any let body: string | Buffer = ''; const headers: IDataObject = {}; for (let i = 0; i < items.length; i++) { - if (resource === 'file') { if (operation === 'download') { // ---------------------------------- @@ -580,7 +580,16 @@ export class NextCloud implements INodeType { options.encoding = null; } - const responseData = await this.helpers.request(options); + try { + responseData = await this.helpers.request(options); + } catch (error) { + if (this.continueOnFail() === true) { + returnData.push({ error }); + continue; + } + + throw error; + } if (resource === 'file' && operation === 'download') { @@ -656,6 +665,7 @@ export class NextCloud implements INodeType { } else { returnData.push(responseData as IDataObject); } + } if (resource === 'file' && operation === 'download') { diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts index 8942225571..8e7fe082e9 100644 --- a/packages/workflow/src/Interfaces.ts +++ b/packages/workflow/src/Interfaces.ts @@ -154,6 +154,7 @@ export interface IExecuteContextData { export interface IExecuteFunctions { + continueOnFail(): boolean; executeWorkflow(workflowInfo: IExecuteWorkflowInfo, inputData?: INodeExecutionData[]): Promise; // tslint:disable-line:no-any getContext(type: string): IContextObject; getCredentials(type: string): ICredentialDataDecryptedObject | undefined; @@ -174,6 +175,7 @@ export interface IExecuteFunctions { export interface IExecuteSingleFunctions { + continueOnFail(): boolean; getContext(type: string): IContextObject; getCredentials(type: string): ICredentialDataDecryptedObject | undefined; getInputData(inputIndex?: number, inputName?: string): INodeExecutionData;