From 3b2078c3caf2a5acee48fed3055b47dbfe0af44a Mon Sep 17 00:00:00 2001 From: Elias Meire Date: Mon, 12 Feb 2024 17:32:27 +0100 Subject: [PATCH] fix(HTTP Request Node): Handle special characters in pagination expressions + improve hint text (#8576) Co-authored-by: Michael Kret --- .../trigger/ChatTrigger/ChatTrigger.node.ts | 4 +- packages/core/src/NodeExecuteFunctions.ts | 24 +- .../InlineExpressionEditorInput.vue | 61 ++--- packages/editor-ui/src/components/Node.vue | 3 +- .../src/composables/useWorkflowHelpers.ts | 2 +- .../HttpRequest/V3/HttpRequestV3.node.ts | 30 ++- .../test/node/workflow.pagination.json | 232 ++++++++++-------- packages/nodes-base/test/nodes/Helpers.ts | 9 +- packages/workflow/src/RoutingNode.ts | 2 +- .../workflow/src/errors/node-api.error.ts | 1 + .../src/errors/node-operation.error.ts | 3 + 11 files changed, 218 insertions(+), 153 deletions(-) diff --git a/packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/ChatTrigger.node.ts b/packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/ChatTrigger.node.ts index 1ca62d1f92..5ac79f74e1 100644 --- a/packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/ChatTrigger.node.ts +++ b/packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/ChatTrigger.node.ts @@ -352,10 +352,10 @@ export class ChatTrigger implements INodeType { await validateAuth(this); } catch (error) { if (error) { - res.writeHead(error.responseCode as number, { + res.writeHead((error as IDataObject).responseCode as number, { 'www-authenticate': 'Basic realm="Webhook"', }); - res.end(error.message as string); + res.end((error as IDataObject).message as string); return { noWebhookResponse: true }; } throw error; diff --git a/packages/core/src/NodeExecuteFunctions.ts b/packages/core/src/NodeExecuteFunctions.ts index 8e5cb6a714..bf2b7784f1 100644 --- a/packages/core/src/NodeExecuteFunctions.ts +++ b/packages/core/src/NodeExecuteFunctions.ts @@ -197,6 +197,17 @@ const createFormDataObject = (data: Record) => { return formData; }; +const validateUrl = (url?: string): boolean => { + if (!url) return false; + + try { + new URL(url); + return true; + } catch (error) { + return false; + } +}; + function searchForHeader(config: AxiosRequestConfig, headerName: string) { if (config.headers === undefined) { return undefined; @@ -1240,7 +1251,10 @@ function applyPaginationRequestData( requestData: OptionsWithUri, paginationRequestData: PaginationOptions['request'], ): OptionsWithUri { - const preparedPaginationData: Partial = { ...paginationRequestData }; + const preparedPaginationData: Partial = { + ...paginationRequestData, + uri: paginationRequestData.url, + }; if ('formData' in requestData) { preparedPaginationData.formData = paginationRequestData.body; @@ -2885,6 +2899,14 @@ const getRequestHelperFunctions = ( const tempRequestOptions = applyPaginationRequestData(requestOptions, paginateRequestData); + if (!validateUrl(tempRequestOptions.uri as string)) { + throw new NodeOperationError(node, `'${paginateRequestData.url}' is not a valid URL.`, { + itemIndex, + runIndex, + type: 'invalid_url', + }); + } + if (credentialsType) { tempResponseData = await this.helpers.requestWithAuthentication.call( this, diff --git a/packages/editor-ui/src/components/InlineExpressionEditor/InlineExpressionEditorInput.vue b/packages/editor-ui/src/components/InlineExpressionEditor/InlineExpressionEditorInput.vue index d34ef873e6..63190abb0b 100644 --- a/packages/editor-ui/src/components/InlineExpressionEditor/InlineExpressionEditorInput.vue +++ b/packages/editor-ui/src/components/InlineExpressionEditor/InlineExpressionEditorInput.vue @@ -3,22 +3,21 @@