Multiple outputs for Custom WebHook

I have a Custom Webhook node that defines multiple webhooks:

webhooks: [
	{
		name: 'voice',
		httpMethod: 'GET',
		responseMode: 'lastNode',
		responseContentType: 'text/xml',
		responsePropertyName: 'data',
		path: '={{$parameter["path"]}}',
	},
	{
		name: 'message',
		httpMethod: 'POST',
		responseMode: 'lastNode',
		responseContentType: 'application/xml',
		path:'={{$parameter["path"]}}',
	},
	{
		name: 'external',
		httpMethod: 'PATCH',
		responseMode: 'lastNode',
		responseContentType: 'application/xml',
		path:'={{$parameter["path"]}}-custom',
	},
],

I am looking to “switch” output within the webhook depending on method called. Since

	async webhook(this: IWebhookFunctions)

should return IWebhookResponseData with a ‘workflow’ property of INodeExecutionData[][], I hoped to add multiple outputs like i do in other nodes by updating my Webhook’s description property with:

 	outputs: ['main', 'main', 'main'],
 	outputNames: ['Call Process', 'Message Process', 'External Data'],

Testing with this as the webhook execution method:

 async webhook(this: IWebhookFunctions): Promise<IWebhookResponseData> {
 	const returnCall: INodeExecutionData[] = [];
	const returnMessage: INodeExecutionData[] = [];
 	const returnExternal: INodeExecutionData[] = [];
	const req = this.getRequestObject();
 	const response: INodeExecutionData = {
		json: {
			body: this.getBodyData(),
			headers: this.getHeaderData(),
			query: this.getQueryData(),
		}
	};
	let hookType = (req.method.toLowerCase() === 'get' ? 'call' :
			(req.method.toLowerCase() === 'post' ? 'message' : 'external'));
	
	if (hookType === 'call'){
		returnCall.push(response);
		console.log('Adding to calls');
	}else if (hookType === 'message'){
		returnMessage.push(response);
		console.log('Adding to messages');
	}else if (hookType === 'external'){
		returnExternal.push(response);
		console.log('Adding to externals');
	}
	console.log([returnCall, returnMessage, returnExternal]);
	return {
		workflow:[returnCall, returnMessage, returnExternal]
	};
}

results only ever send the data to the first output “Call Process”. It doesnt complain about anything, I just never see either of the other outputs hit when using the additional webhook methods.
My console logging shows that the different methods are hit and the final workflow array value has only one of the three subarrays populated with any objects.

Welcome to the community @Jed!

Yes, that is probably a bug. Looks like for some reason does it only run and output data for the other outputs if also output 0 has data. We will check it out.

I checked and found the bug. Will be released with the next version. I gonna update here once it is available.

Btw. you can directly query the name of the webhook with this.getWebhookName(). That will then return voice, message or external and so make your code a little bit simpler.

Fix got released with [email protected]

This now works how I expected.

Thank you

Great to hear! Have fun!

hi,
I want to use the same scenario for the approval node with the wait and switch nodes. And the response has gone through only the first output(0. index).

could you have any suggestion?

export class Approval implements INodeType {
	description: INodeTypeDescription = {
		displayName: 'Approval',
		name: 'approval',
		inputs: ['main'],
		outputs: ['main', 'main', 'main'],
		outputNames: ['Approve', 'Reject', 'Return'],
  }
}

async webhook(this: IWebhookFunctions): Promise<IWebhookResponseData> {
  .
  .
  .

	const returnApprove: INodeExecutionData[] = [];
	const returnReject: INodeExecutionData[] = [];
	const returnReturn: INodeExecutionData[] = [];
	const query = response.json.query as IDataObject || {};
	if (query['action'] === 'Approve') {
		returnApprove.push(response);
	}
	if (query['action'] === 'Reject') {
		returnReject.push(response);
	}
	if (query['action'] === 'Return') {
		returnReturn.push(response);
	}
	
	// outputNames: ['Approve', 'Reject', 'Return'],
	console.log([returnApprove, returnReject, returnReturn]);
	return {
		workflowData:[returnApprove, returnReject, returnReturn],
	};
}

Welcome to the community @Yalcin_Ari !

I am not sure I understand. Do you mean that even if you try to return data to the other outputs, they always just end up in the first one (index: 0)?

And what does that have to do with the wait and the switch nodes?

@jan thank you for your quick response,
Actually, it is only directed first one. When I tried others nothing happened.
I have many workflows that have user interaction in order to approve or reject. For simplicity in design, I want to combine wait and switch nodes, so my colleagues can easily use the “Approval” custom node for new workflows.

action: Approve

action: Reject

Hey @Yalcin_Ari,

What does your console output show?

hi @Jon,
There is nothing on console about it. Now, I am looking for the debugging custom node. But I didn’t figure it out yet.

setup:

  • n8n installed globally
  • custom node linked to global n8n root

Hey @Yalcin_Ari,

That is odd, I noticed the console.log() in your code which tends to output from the n8n process so would normally be in the same window where you ran n8n start.

What happens if you just do…

return [returnApprove, returnReject, returnReturn];

Hey, @Jon

Finally, I found the log.

[ , [ { json: [Object] } ], ]
2023-01-10T05:21:46.885Z [Rudder] error: got error while attempting send for 3 times, dropping 1 events

return [returnApprove, returnReject, returnReturn];

I tried this. but there exists a type mismatch for this. webhook function restricts the return type.

Hey @Yalcin_Ari,

I see if I can find some time to build a test node that handles this as without seeing all of your code and giving it a run I am having a hard time working out where the issue is.

Hey @Jon
I split it into two sequential nodes as below.
Thank you

1 Like