From 33d97843194c1cddfd27356c279c0f7a8c2674d3 Mon Sep 17 00:00:00 2001 From: agobrech <45268029+agobrech@users.noreply.github.com> Date: Mon, 20 Mar 2023 17:34:14 +0100 Subject: [PATCH] fix(core): Improve axios error handling in nodes (#5699) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(core): Improve axios error handling in nodes * handle axios errors without a response (like when connection fails) --------- Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ --- packages/core/package.json | 2 + packages/core/src/NodeExecuteFunctions.ts | 70 +++++++++++------------ pnpm-lock.yaml | 4 ++ 3 files changed, 40 insertions(+), 36 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index 472e4ec1f6757..ad2cbc47d0835 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -39,6 +39,7 @@ "@types/crypto-js": "^4.0.1", "@types/express": "^4.17.6", "@types/lodash.get": "^4.4.6", + "@types/lodash.pick": "^4.4.7", "@types/mime-types": "^2.1.0", "@types/request-promise-native": "~1.0.15", "@types/uuid": "^8.3.2" @@ -54,6 +55,7 @@ "flatted": "^3.2.4", "form-data": "^4.0.0", "lodash.get": "^4.4.2", + "lodash.pick": "^4.4.0", "mime-types": "^2.1.27", "n8n-workflow": "workspace:*", "oauth-1.0a": "^2.2.6", diff --git a/packages/core/src/NodeExecuteFunctions.ts b/packages/core/src/NodeExecuteFunctions.ts index 0e1d88876d26b..70eced6ee6690 100644 --- a/packages/core/src/NodeExecuteFunctions.ts +++ b/packages/core/src/NodeExecuteFunctions.ts @@ -73,6 +73,7 @@ import { ExpressionError, } from 'n8n-workflow'; +import pick from 'lodash.pick'; import { Agent } from 'https'; import { stringify } from 'qs'; import type { Token } from 'oauth-1.0a'; @@ -667,50 +668,47 @@ async function proxyRequestToAxios( return body; } } catch (error) { - const { request, response, isAxiosError, toJSON, config, ...errorData } = error; - if (configObject.simple === false && response) { - if (configObject.resolveWithFullResponse) { - return { - body: response.data, - headers: response.headers, - statusCode: response.status, - statusMessage: response.statusText, - }; - } else { - return response.data; - } - } + const { config, response } = error; // Axios hydrates the original error with more data. We extract them. // https://github.com/axios/axios/blob/master/lib/core/enhanceError.js // Note: `code` is ignored as it's an expected part of the errorData. - if (response) { - Logger.debug('Request proxied to Axios failed', { status: response.status }); - let responseData = response.data; + if (error.isAxiosError) { + if (response) { + Logger.debug('Request proxied to Axios failed', { status: response.status }); + let responseData = response.data; + + if (Buffer.isBuffer(responseData) || responseData instanceof Readable) { + responseData = await binaryToBuffer(responseData).then((buffer) => + buffer.toString('utf-8'), + ); + } - if (Buffer.isBuffer(responseData) || responseData instanceof Readable) { - responseData = await binaryToBuffer(responseData).then((buffer) => - buffer.toString('utf-8'), - ); + if (configObject.simple === false) { + if (configObject.resolveWithFullResponse) { + return { + body: responseData, + headers: response.headers, + statusCode: response.status, + statusMessage: response.statusText, + }; + } else { + return responseData; + } + } + + const message = `${response.status as number} - ${JSON.stringify(responseData)}`; + throw Object.assign(new Error(message, { cause: error }), { + status: response.status, + options: pick(config ?? {}, ['url', 'method', 'data', 'headers']), + }); + } else { + throw Object.assign(new Error(error.message, { cause: error }), { + options: pick(config ?? {}, ['url', 'method', 'data', 'headers']), + }); } - error.message = `${response.status as number} - ${JSON.stringify(responseData)}`; } - error.cause = errorData; - error.error = error.response?.data || errorData; - error.statusCode = error.response?.status; - error.options = config || {}; - - // Remove not needed data and so also remove circular references - error.request = undefined; - error.config = undefined; - error.options.adapter = undefined; - error.options.httpsAgent = undefined; - error.options.paramsSerializer = undefined; - error.options.transformRequest = undefined; - error.options.transformResponse = undefined; - error.options.validateStatus = undefined; - throw error; } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 06fdd35d03ef8..0e426c6e6e60a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -404,6 +404,7 @@ importers: '@types/crypto-js': ^4.0.1 '@types/express': ^4.17.6 '@types/lodash.get': ^4.4.6 + '@types/lodash.pick': ^4.4.7 '@types/mime-types': ^2.1.0 '@types/request-promise-native': ~1.0.15 '@types/uuid': ^8.3.2 @@ -417,6 +418,7 @@ importers: flatted: ^3.2.4 form-data: ^4.0.0 lodash.get: ^4.4.2 + lodash.pick: ^4.4.0 mime-types: ^2.1.27 n8n-workflow: workspace:* oauth-1.0a: ^2.2.6 @@ -437,6 +439,7 @@ importers: flatted: 3.2.7 form-data: 4.0.0 lodash.get: 4.4.2 + lodash.pick: 4.4.0 mime-types: 2.1.35 n8n-workflow: link:../workflow oauth-1.0a: 2.2.6 @@ -452,6 +455,7 @@ importers: '@types/crypto-js': 4.1.1 '@types/express': 4.17.14 '@types/lodash.get': 4.4.7 + '@types/lodash.pick': 4.4.7 '@types/mime-types': 2.1.1 '@types/request-promise-native': 1.0.18 '@types/uuid': 8.3.4