mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-12-19 03:42:23 -06:00
feat(env): enhance webhook configuration and SSL support
- Added new environment variables for SSL configuration, including `SSL_CONF_PRIVKEY` and `SSL_CONF_FULLCHAIN`, to support secure connections. - Introduced additional webhook configuration options in the `.env.example` file, such as `WEBHOOK_REQUEST_TIMEOUT_MS`, `WEBHOOK_RETRY_MAX_ATTEMPTS`, and related retry settings to improve webhook resilience and error handling. - Updated the `bootstrap` function in `main.ts` to handle SSL certificate loading failures gracefully, falling back to HTTP if necessary. - Enhanced error handling and logging in the `BusinessStartupService` to ensure better traceability and robustness when processing messages. This commit focuses on improving the security and reliability of webhook interactions while ensuring that the application can handle SSL configurations effectively.
This commit is contained in:
@@ -125,6 +125,7 @@ export class WebhookController extends EventController implements EventControlle
|
||||
const httpService = axios.create({
|
||||
baseURL,
|
||||
headers: webhookHeaders as Record<string, string> | undefined,
|
||||
timeout: webhookConfig.REQUEST?.TIMEOUT_MS ?? 30000,
|
||||
});
|
||||
|
||||
await this.retryWebhookRequest(httpService, webhookData, `${origin}.sendData-Webhook`, baseURL, serverUrl);
|
||||
@@ -166,7 +167,10 @@ export class WebhookController extends EventController implements EventControlle
|
||||
|
||||
try {
|
||||
if (regex.test(globalURL)) {
|
||||
const httpService = axios.create({ baseURL: globalURL });
|
||||
const httpService = axios.create({
|
||||
baseURL: globalURL,
|
||||
timeout: webhookConfig.REQUEST?.TIMEOUT_MS ?? 30000,
|
||||
});
|
||||
|
||||
await this.retryWebhookRequest(
|
||||
httpService,
|
||||
@@ -200,12 +204,20 @@ export class WebhookController extends EventController implements EventControlle
|
||||
origin: string,
|
||||
baseURL: string,
|
||||
serverUrl: string,
|
||||
maxRetries = 10,
|
||||
delaySeconds = 30,
|
||||
maxRetries?: number,
|
||||
delaySeconds?: number,
|
||||
): Promise<void> {
|
||||
const webhookConfig = configService.get<Webhook>('WEBHOOK');
|
||||
const maxRetryAttempts = maxRetries ?? webhookConfig.RETRY?.MAX_ATTEMPTS ?? 10;
|
||||
const initialDelay = delaySeconds ?? webhookConfig.RETRY?.INITIAL_DELAY_SECONDS ?? 5;
|
||||
const useExponentialBackoff = webhookConfig.RETRY?.USE_EXPONENTIAL_BACKOFF ?? true;
|
||||
const maxDelay = webhookConfig.RETRY?.MAX_DELAY_SECONDS ?? 300;
|
||||
const jitterFactor = webhookConfig.RETRY?.JITTER_FACTOR ?? 0.2;
|
||||
const nonRetryableStatusCodes = webhookConfig.RETRY?.NON_RETRYABLE_STATUS_CODES ?? [400, 401, 403, 404, 422];
|
||||
|
||||
let attempts = 0;
|
||||
|
||||
while (attempts < maxRetries) {
|
||||
while (attempts < maxRetryAttempts) {
|
||||
try {
|
||||
await httpService.post('', webhookData);
|
||||
if (attempts > 0) {
|
||||
@@ -219,12 +231,27 @@ export class WebhookController extends EventController implements EventControlle
|
||||
} catch (error) {
|
||||
attempts++;
|
||||
|
||||
const isTimeout = error.code === 'ECONNABORTED';
|
||||
|
||||
if (error?.response?.status && nonRetryableStatusCodes.includes(error.response.status)) {
|
||||
this.logger.error({
|
||||
local: `${origin}`,
|
||||
message: `Erro não recuperável (${error.response.status}): ${error?.message}. Cancelando retentativas.`,
|
||||
statusCode: error?.response?.status,
|
||||
url: baseURL,
|
||||
server_url: serverUrl,
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.logger.error({
|
||||
local: `${origin}`,
|
||||
message: `Tentativa ${attempts}/${maxRetries} falhou: ${error?.message}`,
|
||||
message: `Tentativa ${attempts}/${maxRetryAttempts} falhou: ${isTimeout ? 'Timeout da requisição' : error?.message}`,
|
||||
hostName: error?.hostname,
|
||||
syscall: error?.syscall,
|
||||
code: error?.code,
|
||||
isTimeout,
|
||||
statusCode: error?.response?.status,
|
||||
error: error?.errno,
|
||||
stack: error?.stack,
|
||||
name: error?.name,
|
||||
@@ -232,11 +259,25 @@ export class WebhookController extends EventController implements EventControlle
|
||||
server_url: serverUrl,
|
||||
});
|
||||
|
||||
if (attempts === maxRetries) {
|
||||
if (attempts === maxRetryAttempts) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, delaySeconds * 1000));
|
||||
let nextDelay = initialDelay;
|
||||
if (useExponentialBackoff) {
|
||||
nextDelay = Math.min(initialDelay * Math.pow(2, attempts - 1), maxDelay);
|
||||
|
||||
const jitter = nextDelay * jitterFactor * (Math.random() * 2 - 1);
|
||||
nextDelay = Math.max(initialDelay, nextDelay + jitter);
|
||||
}
|
||||
|
||||
this.logger.log({
|
||||
local: `${origin}`,
|
||||
message: `Aguardando ${nextDelay.toFixed(1)} segundos antes da próxima tentativa`,
|
||||
url: baseURL,
|
||||
});
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, nextDelay * 1000));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user