diff --git a/packages/core/src/execution-engine/__tests__/routing-node.test.ts b/packages/core/src/execution-engine/__tests__/routing-node.test.ts index 83c8e6213be03..5fa655632d0ea 100644 --- a/packages/core/src/execution-engine/__tests__/routing-node.test.ts +++ b/packages/core/src/execution-engine/__tests__/routing-node.test.ts @@ -100,6 +100,7 @@ const getExecuteSingleFunctions = ( describe('RoutingNode', () => { const nodeTypes = NodeTypes(); const additionalData = mock({ + executionId: 'test-exec-123', webhookWaitingBaseUrl: 'http://localhost:5678/webhook-waiting', formWaitingBaseUrl: 'http://localhost:5678/form-waiting', }); @@ -753,6 +754,7 @@ describe('RoutingNode', () => { mode, connectionInputData, runExecutionData, + nodeType, }); const routingNode = new RoutingNode(executeFunctions, nodeType); @@ -790,7 +792,7 @@ describe('RoutingNode', () => { nodeType: { properties?: INodeProperties[]; credentials?: INodeCredentialDescription[]; - requestDefaults?: IHttpRequestOptions; + requestDefaults?: DeclarativeRestApiSettings.HttpRequestOptions; requestOperations?: IN8nRequestOperations; }; node: { @@ -2057,6 +2059,124 @@ describe('RoutingNode', () => { ], ], }, + { + description: 'single parameter, routing.request.url resolves $execution.id', + input: { + node: { + parameters: { + resource: 'executions', + }, + }, + nodeType: { + requestDefaults: { + baseURL: 'http://127.0.0.1:5678', + }, + properties: [ + { + displayName: 'Resource', + name: 'resource', + type: 'string', + routing: { + request: { + method: 'GET', + url: '=/{{$value}}/{{ $execution.id }}', + }, + }, + default: '', + }, + ], + }, + }, + output: [ + [ + { + json: { + headers: {}, + statusCode: 200, + requestOptions: { + url: '/executions/test-exec-123', + method: 'GET', + headers: {}, + qs: {}, + body: {}, + baseURL: 'http://127.0.0.1:5678', + returnFullResponse: true, + timeout: 300000, + }, + }, + }, + ], + ], + }, + { + description: + 'options parameter with routing.request.url on selected option resolves $execution.id via $parameter', + input: { + node: { + parameters: { + operation: 'get', + executionId: '={{ $execution.id }}', + }, + }, + nodeType: { + requestDefaults: { + baseURL: 'http://127.0.0.1:5678', + }, + properties: [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + noDataExpression: true, + default: 'get', + options: [ + { + name: 'Get', + value: 'get', + routing: { + request: { + method: 'GET', + url: '=/executions/{{ $parameter.executionId }}', + }, + }, + }, + ], + }, + { + displayName: 'Execution ID', + name: 'executionId', + type: 'string', + default: '', + displayOptions: { + show: { + operation: ['get'], + }, + }, + }, + ], + }, + }, + output: [ + [ + { + json: { + headers: {}, + statusCode: 200, + requestOptions: { + url: '/executions/test-exec-123', + method: 'GET', + headers: {}, + qs: {}, + body: {}, + baseURL: 'http://127.0.0.1:5678', + returnFullResponse: true, + timeout: 300000, + }, + }, + }, + ], + ], + }, ]; const baseNode: INode = { diff --git a/packages/core/src/execution-engine/routing-node.ts b/packages/core/src/execution-engine/routing-node.ts index ddce65320158d..d1c7cf3326a22 100644 --- a/packages/core/src/execution-engine/routing-node.ts +++ b/packages/core/src/execution-engine/routing-node.ts @@ -40,6 +40,7 @@ import type { import url from 'node:url'; import { type ExecuteContext, ExecuteSingleContext } from './node-execution-context'; +import { getAdditionalKeys } from './node-execution-context/utils/get-additional-keys'; export class RoutingNode { constructor( @@ -132,6 +133,8 @@ export class RoutingNode { }; } + const additionalKeys = getAdditionalKeys(additionalData, mode, runExecutionData); + if (nodeType.description.requestDefaults) { for (const key of Object.keys(nodeType.description.requestDefaults)) { // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -142,7 +145,7 @@ export class RoutingNode { itemIndex, runIndex, executeData, - { $credentials: credentials, $version: node.typeVersion }, + { ...additionalKeys, $credentials: credentials, $version: node.typeVersion }, false, ) as string; // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -158,7 +161,7 @@ export class RoutingNode { itemIndex, runIndex, executeData, - { $credentials: credentials, $version: node.typeVersion }, + { ...additionalKeys, $credentials: credentials, $version: node.typeVersion }, false, ) as string | NodeParameterValue; @@ -168,7 +171,12 @@ export class RoutingNode { itemIndex, runIndex, '', - { $credentials: credentials, $value: value, $version: node.typeVersion }, + { + ...additionalKeys, + $credentials: credentials, + $value: value, + $version: node.typeVersion, + }, ); this.mergeOptions(itemContext[itemIndex].requestData, tempOptions); @@ -850,7 +858,7 @@ export class RoutingNode { itemIndex, runIndex, executeSingleFunctions.getExecuteData(), - additionalKeys, + { ...additionalKeys, $value: parameterValue }, true, ) as string; @@ -993,7 +1001,7 @@ export class RoutingNode { itemIndex, runIndex, `${basePath}${nodeProperties.name}`, - { $value: optionValue, $version: node.typeVersion }, + { ...additionalKeys, $value: optionValue, $version: node.typeVersion }, ); this.mergeOptions(returnData, tempOptions); @@ -1017,7 +1025,7 @@ export class RoutingNode { itemIndex, runIndex, `${basePath}${nodeProperties.name}`, - { $version: node.typeVersion }, + { ...additionalKeys, $version: node.typeVersion }, ); this.mergeOptions(returnData, tempOptions); @@ -1061,7 +1069,11 @@ export class RoutingNode { itemIndex, runIndex, nodeProperties.typeOptions?.multipleValues ? `${loopBasePath}[${i}]` : loopBasePath, - { ...(additionalKeys || {}), $index: i, $parent: value[i] }, + { + ...(additionalKeys || {}), + $index: i, + $parent: value[i], + }, ); this.mergeOptions(returnData, tempOptions);