mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-18 02:21:13 +00:00
fix(core): Handle dynamic webhook edge cases (#16554)
This commit is contained in:
@@ -386,4 +386,116 @@ describe('WebhookService', () => {
|
|||||||
expect(webhookRepository.findBy).toHaveBeenCalledTimes(2);
|
expect(webhookRepository.findBy).toHaveBeenCalledTimes(2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('isDynamicPath', () => {
|
||||||
|
test.each(['a', 'a/b'])('should treat static path (%s) as static', (path) => {
|
||||||
|
const workflow = new Workflow({
|
||||||
|
id: 'test-workflow',
|
||||||
|
nodes: [],
|
||||||
|
connections: {},
|
||||||
|
active: true,
|
||||||
|
nodeTypes,
|
||||||
|
});
|
||||||
|
|
||||||
|
const node = mock<INode>({
|
||||||
|
name: 'Webhook',
|
||||||
|
type: 'n8n-nodes-base.webhook',
|
||||||
|
});
|
||||||
|
|
||||||
|
const nodeType = mock<INodeType>({
|
||||||
|
description: {
|
||||||
|
webhooks: [
|
||||||
|
{
|
||||||
|
name: 'default',
|
||||||
|
httpMethod: 'GET',
|
||||||
|
path,
|
||||||
|
isFullPath: false,
|
||||||
|
restartWebhook: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
nodeTypes.getByNameAndVersion.mockReturnValue(nodeType);
|
||||||
|
|
||||||
|
const webhooks = webhookService.getNodeWebhooks(workflow, node, additionalData);
|
||||||
|
|
||||||
|
expect(webhooks).toHaveLength(1);
|
||||||
|
expect(webhooks[0].webhookId).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test.each([':', '/:'])('should treat literal colon path (%s) as static', (path) => {
|
||||||
|
const workflow = new Workflow({
|
||||||
|
id: 'test-workflow',
|
||||||
|
nodes: [],
|
||||||
|
connections: {},
|
||||||
|
active: true,
|
||||||
|
nodeTypes,
|
||||||
|
});
|
||||||
|
|
||||||
|
const nodeWithWebhookId = mock<INode>({
|
||||||
|
name: 'Webhook',
|
||||||
|
type: 'n8n-nodes-base.webhook',
|
||||||
|
});
|
||||||
|
|
||||||
|
const nodeType = mock<INodeType>({
|
||||||
|
description: {
|
||||||
|
webhooks: [
|
||||||
|
{
|
||||||
|
name: 'default',
|
||||||
|
httpMethod: 'GET',
|
||||||
|
path,
|
||||||
|
isFullPath: false,
|
||||||
|
restartWebhook: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
nodeTypes.getByNameAndVersion.mockReturnValue(nodeType);
|
||||||
|
|
||||||
|
const webhooks = webhookService.getNodeWebhooks(workflow, nodeWithWebhookId, additionalData);
|
||||||
|
|
||||||
|
expect(webhooks).toHaveLength(1);
|
||||||
|
expect(webhooks[0].webhookId).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should treat dynamic path (user/:id) as dynamic', () => {
|
||||||
|
const workflow = new Workflow({
|
||||||
|
id: 'test-workflow',
|
||||||
|
nodes: [],
|
||||||
|
connections: {},
|
||||||
|
active: true,
|
||||||
|
nodeTypes,
|
||||||
|
});
|
||||||
|
|
||||||
|
const nodeWithWebhookId = mock<INode>({
|
||||||
|
name: 'Webhook',
|
||||||
|
type: 'n8n-nodes-base.webhook',
|
||||||
|
disabled: false,
|
||||||
|
webhookId: 'test-webhook-id',
|
||||||
|
});
|
||||||
|
|
||||||
|
const nodeType = mock<INodeType>({
|
||||||
|
description: {
|
||||||
|
webhooks: [
|
||||||
|
{
|
||||||
|
name: 'default',
|
||||||
|
httpMethod: 'GET',
|
||||||
|
path: 'user/:id',
|
||||||
|
isFullPath: false,
|
||||||
|
restartWebhook: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
nodeTypes.getByNameAndVersion.mockReturnValue(nodeType);
|
||||||
|
|
||||||
|
const webhooks = webhookService.getNodeWebhooks(workflow, nodeWithWebhookId, additionalData);
|
||||||
|
|
||||||
|
expect(webhooks).toHaveLength(1);
|
||||||
|
expect(webhooks[0].webhookId).toBe('test-webhook-id');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -139,6 +139,17 @@ export class WebhookService {
|
|||||||
.then((rows) => rows.map((r) => r.method));
|
.then((rows) => rows.map((r) => r.method));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private isDynamicPath(rawPath: string) {
|
||||||
|
const firstSlashIndex = rawPath.indexOf('/');
|
||||||
|
const path = firstSlashIndex !== -1 ? rawPath.substring(firstSlashIndex + 1) : rawPath;
|
||||||
|
|
||||||
|
// if dynamic, first segment is webhook ID so disregard it
|
||||||
|
|
||||||
|
if (path === '' || path === ':' || path === '/:') return false;
|
||||||
|
|
||||||
|
return path.startsWith(':') || path.includes('/:');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all the webhooks which should be created for the give node
|
* Returns all the webhooks which should be created for the give node
|
||||||
*/
|
*/
|
||||||
@@ -232,7 +243,8 @@ export class WebhookService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let webhookId: string | undefined;
|
let webhookId: string | undefined;
|
||||||
if ((path.startsWith(':') || path.includes('/:')) && node.webhookId) {
|
|
||||||
|
if (this.isDynamicPath(path) && node.webhookId) {
|
||||||
webhookId = node.webhookId;
|
webhookId = node.webhookId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user