fix(core): Deduplicate error handling in nodes (#4319)

* Fix issue with isAxios property

* 🥅 Deduplicate errors handeling improve errors for credentials

* 🎨 correctly throws error
This commit is contained in:
agobrech 2022-11-11 11:32:43 +01:00 committed by GitHub
parent d35d63a855
commit c7133ecd3f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 50 additions and 187 deletions

View file

@ -39,11 +39,7 @@ export async function actionNetworkApiRequest(
delete options.qs;
}
try {
return await this.helpers.requestWithAuthentication.call(this, 'actionNetworkApi', options);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
return await this.helpers.requestWithAuthentication.call(this, 'actionNetworkApi', options);
}
export async function handleListing(

View file

@ -61,11 +61,7 @@ export async function apiRequest(
delete options.body;
}
try {
return await this.helpers.requestWithAuthentication.call(this, 'airtableApi', options);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
return await this.helpers.requestWithAuthentication.call(this, 'airtableApi', options);
}
/**

View file

@ -7,6 +7,7 @@ import {
IWebhookFunctions,
} from 'n8n-core';
import { IHttpRequestOptions, NodeApiError } from 'n8n-workflow';
export async function awsApiRequest(
@ -31,11 +32,7 @@ export async function awsApiRequest(
headers,
region: credentials?.region as string,
} as IHttpRequestOptions;
try {
return await this.helpers.requestWithAuthentication.call(this, 'aws', requestOptions);
} catch (error) {
throw new NodeApiError(this.getNode(), error); // no XML parsing needed
}
return await this.helpers.requestWithAuthentication.call(this, 'aws', requestOptions);
}
export async function awsApiRequestREST(

View file

@ -42,11 +42,7 @@ export async function awsApiRequest(
if (Object.keys(option).length !== 0) {
Object.assign(requestOptions, option);
}
try {
return await this.helpers.requestWithAuthentication.call(this, 'aws', requestOptions);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
return await this.helpers.requestWithAuthentication.call(this, 'aws', requestOptions);
}
export async function awsApiRequestREST(

View file

@ -40,11 +40,7 @@ export async function awsApiRequest(
if (Object.keys(option).length !== 0) {
Object.assign(requestOptions, option);
}
try {
return await this.helpers.requestWithAuthentication.call(this, 'aws', requestOptions);
} catch (error) {
throw new NodeApiError(this.getNode(), error as JsonObject);
}
return await this.helpers.requestWithAuthentication.call(this, 'aws', requestOptions);
}
export async function awsApiRequestREST(

View file

@ -31,11 +31,7 @@ export async function beeminderApiRequest(
delete options.qs;
}
try {
return await this.helpers.requestWithAuthentication.call(this, 'beeminderApi', options);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
return await this.helpers.requestWithAuthentication.call(this, 'beeminderApi', options);
}
export async function beeminderApiRequestAllItems(

View file

@ -53,11 +53,7 @@ export async function calendlyApiRequest(
delete options.qs;
}
options = Object.assign({}, options, option);
try {
return await this.helpers.requestWithAuthentication.call(this, 'calendlyApi', options);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
return await this.helpers.requestWithAuthentication.call(this, 'calendlyApi', options);
}
export function getAuthenticationType(data: string): 'accessToken' | 'apiKey' {

View file

@ -28,12 +28,7 @@ export async function clockifyApiRequest(
json: true,
useQuerystring: true,
};
try {
return await this.helpers.requestWithAuthentication.call(this, 'clockifyApi', options);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
return await this.helpers.requestWithAuthentication.call(this, 'clockifyApi', options);
}
export async function clockifyApiRequestAllItems(

View file

@ -42,11 +42,7 @@ export async function cortexApiRequest(
delete options.qs;
}
try {
return await this.helpers.requestWithAuthentication.call(this, 'cortexApi', options);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
return await this.helpers.requestWithAuthentication.call(this, 'cortexApi', options);
}
export function getEntityLabel(entity: IDataObject): string {

View file

@ -32,11 +32,7 @@ export async function customerIoApiRequest(
options.url = `https://beta-api.customer.io/v1/api${endpoint}`;
}
try {
return await this.helpers.requestWithAuthentication.call(this, 'customerIoApi', options);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
return await this.helpers.requestWithAuthentication.call(this, 'customerIoApi', options);
}
export function eventExists(currentEvents: string[], webhookEvents: IDataObject) {

View file

@ -30,9 +30,5 @@ export async function dropcontactApiRequest(
delete options.qs;
}
try {
return await this.helpers.requestWithAuthentication.call(this, 'dropcontactApi', options);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
return await this.helpers.requestWithAuthentication.call(this, 'dropcontactApi', options);
}

View file

@ -50,8 +50,7 @@ export async function erpNextApiRequest(
message: 'Please ensure the subdomain is correct.',
});
}
throw new NodeApiError(this.getNode(), error);
throw error;
}
}

View file

@ -44,11 +44,7 @@ export async function ghostApiRequest(
json: true,
};
try {
return await this.helpers.requestWithAuthentication.call(this, credentialType, options);
} catch (error) {
throw new NodeApiError(this.getNode(), error as JsonObject);
}
return await this.helpers.requestWithAuthentication.call(this, credentialType, options);
}
export async function ghostApiRequestAllItems(

View file

@ -232,13 +232,7 @@ export async function highLevelApiRequest(
delete options.qs;
}
options = Object.assign({}, options, option);
try {
return await this.helpers.requestWithAuthentication.call(this, 'highLevelApi', options);
} catch (error) {
throw new NodeApiError(this.getNode(), error, {
message: error.message,
});
}
return await this.helpers.requestWithAuthentication.call(this, 'highLevelApi', options);
}
export async function getPipelineStages(

View file

@ -58,11 +58,7 @@ export async function jiraSoftwareCloudApiRequest(
delete options.qs;
}
try {
return await this.helpers.requestWithAuthentication.call(this, credentialType, options);
} catch (error) {
throw new NodeApiError(this.getNode(), error as JsonObject);
}
return await this.helpers.requestWithAuthentication.call(this, credentialType, options);
}
export async function jiraSoftwareCloudApiRequestAllItems(

View file

@ -17,10 +17,8 @@ export async function lemlistApiRequest(
qs: IDataObject = {},
option: IDataObject = {},
) {
const options: OptionsWithUri = {
headers: {
},
headers: {},
method,
uri: `https://api.lemlist.com/api${endpoint}`,
qs,
@ -40,11 +38,7 @@ export async function lemlistApiRequest(
Object.assign(options, option);
}
try {
return await this.helpers.requestWithAuthentication.call(this,'lemlistApi',options);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
return await this.helpers.requestWithAuthentication.call(this, 'lemlistApi', options);
}
/**

View file

@ -48,11 +48,7 @@ export async function mailjetApiRequest(
delete options.body;
}
try {
return await this.helpers.requestWithAuthentication.call(this, credentialType, options);
} catch (error) {
throw new NodeApiError(this.getNode(), error as JsonObject);
}
return await this.helpers.requestWithAuthentication.call(this, credentialType, options);
}
export async function mailjetApiRequestAllItems(

View file

@ -54,10 +54,5 @@ export async function nextCloudApiRequest(
const credentialType =
authenticationMethod === 'accessToken' ? 'nextCloudApi' : 'nextCloudOAuth2Api';
try {
return await this.helpers.requestWithAuthentication.call(this, credentialType, options);
} catch (error) {
throw new NodeApiError(this.getNode(), error as JsonObject);
}
return await this.helpers.requestWithAuthentication.call(this, credentialType, options);
}

View file

@ -61,11 +61,7 @@ export async function apiRequest(
delete options.body;
}
try {
return await this.helpers.requestWithAuthentication.call(this, authenticationMethod, options);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
return await this.helpers.requestWithAuthentication.call(this, authenticationMethod, options);
}
/**

View file

@ -25,11 +25,7 @@ export async function rocketchatApiRequest(
if (Object.keys(options.body).length === 0) {
delete options.body;
}
try {
return await this.helpers.requestWithAuthentication.call(this, 'rocketchatApi', options);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
return await this.helpers.requestWithAuthentication.call(this, 'rocketchatApi', options);
}
// tslint:disable-next-line:no-any

View file

@ -36,9 +36,5 @@ export async function segmentApiRequest(
if (!Object.keys(body).length) {
delete options.body;
}
try {
return await this.helpers.requestWithAuthentication.call(this, 'segmentApi', options);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
return await this.helpers.requestWithAuthentication.call(this, 'segmentApi', options);
}

View file

@ -37,11 +37,7 @@ export async function sendGridApiRequest(
Object.assign(options, option);
}
try {
return await this.helpers.requestWithAuthentication.call(this, 'sendGridApi', options);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
return await this.helpers.requestWithAuthentication.call(this, 'sendGridApi', options);
}
export async function sendGridApiRequestAllItems(

View file

@ -66,13 +66,9 @@ export async function shopifyApiRequest(
delete options.qs;
}
try {
return await this.helpers.requestWithAuthentication.call(this, credentialType, options, {
oauth2: oAuth2Options,
});
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
return await this.helpers.requestWithAuthentication.call(this, credentialType, options, {
oauth2: oAuth2Options,
});
}
export async function shopifyApiRequestAllItems(

View file

@ -29,11 +29,7 @@ export async function stripeApiRequest(
delete options.qs;
}
try {
return await this.helpers.requestWithAuthentication.call(this, 'stripeApi', options);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
return await this.helpers.requestWithAuthentication.call(this, 'stripeApi', options);
}
/**

View file

@ -40,11 +40,7 @@ export async function theHiveApiRequest(
if (Object.keys(query).length === 0) {
delete options.qs;
}
try {
return await this.helpers.requestWithAuthentication.call(this, 'theHiveApi', options);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
return await this.helpers.requestWithAuthentication.call(this, 'theHiveApi', options);
}
// Helpers functions

View file

@ -26,14 +26,7 @@ export async function apiRequest(
json: true,
};
try {
return await this.helpers.requestWithAuthentication.call(this, 'trelloApi', options);
} catch (error) {
if (error instanceof NodeApiError) {
throw error;
}
throw new NodeApiError(this.getNode(), error as JsonObject);
}
return await this.helpers.requestWithAuthentication.call(this, 'trelloApi', options);
}
export async function apiRequestAllItems(

View file

@ -31,12 +31,5 @@ export async function twakeApiRequest(
// options.uri = `${credentials!.hostUrl}/api/v1${resource}`;
// }
try {
return await this.helpers.requestWithAuthentication.call(this, 'twakeCloudApi', options);
} catch (error) {
if (error.error?.code === 'ECONNREFUSED') {
throw new NodeApiError(this.getNode(), error, { message: 'Twake host is not accessible!' });
}
throw new NodeApiError(this.getNode(), error);
}
return await this.helpers.requestWithAuthentication.call(this, 'twakeCloudApi', options);
}

View file

@ -36,11 +36,7 @@ export async function twilioApiRequest(
json: true,
};
try {
return await this.helpers.requestWithAuthentication.call(this, 'twilioApi', options);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
return await this.helpers.requestWithAuthentication.call(this, 'twilioApi', options);
}
const XML_CHAR_MAP: { [key: string]: string } = {

View file

@ -27,11 +27,7 @@ export async function urlScanIoApiRequest(
delete options.qs;
}
try {
return await this.helpers.requestWithAuthentication.call(this, 'urlScanIoApi', options);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
return await this.helpers.requestWithAuthentication.call(this, 'urlScanIoApi', options);
}
export async function handleListing(

View file

@ -48,11 +48,7 @@ export async function webflowApiRequest(
if (Object.keys(options.body).length === 0) {
delete options.body;
}
try {
return await this.helpers.requestWithAuthentication.call(this, credentialsType, options);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
return await this.helpers.requestWithAuthentication.call(this, credentialsType, options);
}
export async function webflowApiRequestAllItems(

View file

@ -27,12 +27,5 @@ export async function apiRequest(
json: true,
};
try {
return await this.helpers.requestWithAuthentication.call(this, 'wekanApi', options);
} catch (error) {
if (error.statusCode === 401) {
throw new NodeOperationError(this.getNode(), 'The Wekan credentials are not valid!');
}
throw new NodeApiError(this.getNode(), error as JsonObject);
}
return await this.helpers.requestWithAuthentication.call(this, 'wekanApi', options);
}

View file

@ -48,11 +48,7 @@ export async function woocommerceApiRequest(
delete options.form;
}
options = Object.assign({}, options, option);
try {
return await this.helpers.requestWithAuthentication.call(this, 'wooCommerceApi', options);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
return await this.helpers.requestWithAuthentication.call(this, 'wooCommerceApi', options);
}
export async function woocommerceApiRequestAllItems(

View file

@ -36,9 +36,5 @@ export async function wufooApiRequest(
delete options.body;
}
try {
return await this.helpers.requestWithAuthentication.call(this, 'wufooApi', options);
} catch (error) {
throw new NodeApiError(this.getNode(), error as JsonObject);
}
return await this.helpers.requestWithAuthentication.call(this, 'wufooApi', options);
}

View file

@ -48,11 +48,7 @@ export async function zendeskApiRequest(
const credentialType = authenticationMethod === 'apiToken' ? 'zendeskApi' : 'zendeskOAuth2Api';
try {
return await this.helpers.requestWithAuthentication.call(this, credentialType, options);
} catch (error) {
throw new NodeApiError(this.getNode(), error as JsonObject);
}
return await this.helpers.requestWithAuthentication.call(this, credentialType, options);
}
/**

View file

@ -255,9 +255,12 @@ const STATUS_CODE_MESSAGES: IStatusCodeMessages = {
'502': 'Bad gateway - the service failed to handle your request',
'503': 'Service unavailable - perhaps try again later?',
'504': 'Gateway timed out - perhaps try again later?',
ECONNREFUSED: 'The service refused the connection - perhaps it is offline',
};
const UNKNOWN_ERROR_MESSAGE = 'UNKNOWN ERROR - check the detailed error for more information';
const UNKNOWN_ERROR_MESSAGE_CRED = 'UNKNOWN ERROR';
interface NodeApiErrorOptions extends NodeOperationErrorOptions {
message?: string;
@ -282,10 +285,14 @@ export class NodeApiError extends NodeError {
// only for request library error
this.removeCircularRefs(error.error as JsonObject);
}
// if it's an error generated by axios
// look for descriptions in the response object
if (error.isAxiosError && error.response) {
error = error.response as JsonObject;
if (error.reason) {
const reason: IDataObject = error.reason as unknown as IDataObject;
if (reason.isAxiosError && reason.response) {
error = reason.response as JsonObject;
}
}
if (message) {
@ -351,5 +358,8 @@ export class NodeApiError extends NodeError {
default:
this.message = UNKNOWN_ERROR_MESSAGE;
}
if (this.node.type === 'n8n-nodes-base.noOp' && this.message === UNKNOWN_ERROR_MESSAGE) {
this.message = `${UNKNOWN_ERROR_MESSAGE_CRED} - ${this.httpCode}`;
}
}
}