mirror of
https://github.com/n8n-io/n8n.git
synced 2025-01-11 04:47:29 -08:00
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:
parent
d35d63a855
commit
c7133ecd3f
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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' {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -50,8 +50,7 @@ export async function erpNextApiRequest(
|
|||
message: 'Please ensure the subdomain is correct.',
|
||||
});
|
||||
}
|
||||
|
||||
throw new NodeApiError(this.getNode(), error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 } = {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue