/* eslint-disable @typescript-eslint/no-explicit-any */ import axios, { AxiosInstance, AxiosRequestConfig, CancelToken, Canceler } from 'axios'; import axiosRetry, { IAxiosRetryConfig } from 'axios-retry'; import { HttpCancellationToken, HttpGet, HttpSettings, Response, RetryStrategySettings } from '../models'; import { getHeaders } from '../utilities/http.utilities.functions'; import { HttpPost, HttpDelete, HttpPatch, HttpPut } from '../models/http-methods'; import { ApiService } from './api.interface'; import { ResponseFactory } from './response.factory'; export class HttpService implements ApiService { private readonly axiosInstance: AxiosInstance; readonly defaultRetryStrategy: IAxiosRetryConfig = { retries: 5, retryDelay: axiosRetry.exponentialDelay }; constructor(settings?: { axiosRequestConfig?: AxiosRequestConfig; axiosInstance?: AxiosInstance }) { if (settings?.axiosInstance) { this.axiosInstance = settings.axiosInstance; } else { this.axiosInstance = axios.create(settings?.axiosRequestConfig); } } async get(method: HttpGet, settings?: HttpSettings): Promise> { const retryStrategyConfig = this.getRetryPolicy(settings?.retryStrategy); const axiosResponse = await this.axiosInstance.get(method.url, { headers: getHeaders(settings?.headers ?? [], false), responseType: settings?.responseType, cancelToken: settings?.cancellationToken?.token, 'axios-retry': retryStrategyConfig }); return ResponseFactory.create(axiosResponse, retryStrategyConfig); } async post(method: HttpPost, settings?: HttpSettings): Promise> { const retryStrategyConfig = this.getRetryPolicy(settings?.retryStrategy); const axiosResponse = await this.axiosInstance.post(method.url, method.body, { headers: getHeaders(settings?.headers ?? [], false), responseType: settings?.responseType, cancelToken: settings?.cancellationToken?.token, maxContentLength: 'Infinity' as any, maxBodyLength: 'Infinity' as any, 'axios-retry': retryStrategyConfig }); return ResponseFactory.create(axiosResponse, retryStrategyConfig); } async delete(method: HttpDelete, settings?: HttpSettings): Promise> { const retryStrategyConfig = this.getRetryPolicy(settings?.retryStrategy); const axiosResponse = await this.axiosInstance.delete(method.url, { headers: getHeaders(settings?.headers ?? [], false), responseType: settings?.responseType, cancelToken: settings?.cancellationToken?.token, maxContentLength: 'Infinity' as any, maxBodyLength: 'Infinity' as any, 'axios-retry': retryStrategyConfig }); return ResponseFactory.create(axiosResponse, retryStrategyConfig); } async patch(method: HttpPatch, settings?: HttpSettings): Promise> { const retryStrategyConfig = this.getRetryPolicy(settings?.retryStrategy); const axiosResponse = await this.axiosInstance.patch(method.url, method.body, { headers: getHeaders(settings?.headers ?? [], false), responseType: settings?.responseType, cancelToken: settings?.cancellationToken?.token, maxContentLength: 'Infinity' as any, maxBodyLength: 'Infinity' as any, 'axios-retry': retryStrategyConfig }); return ResponseFactory.create(axiosResponse, retryStrategyConfig); } async put(method: HttpPut, settings?: HttpSettings): Promise> { const retryStrategyConfig = this.getRetryPolicy(settings?.retryStrategy); const axiosResponse = await this.axiosInstance.patch(method.url, method.body, { headers: getHeaders(settings?.headers ?? [], false), responseType: settings?.responseType, cancelToken: settings?.cancellationToken?.token, maxContentLength: 'Infinity' as any, maxBodyLength: 'Infinity' as any, 'axios-retry': retryStrategyConfig }); return ResponseFactory.create(axiosResponse, retryStrategyConfig); } createCancellationToken(): HttpCancellationToken { let canceler: Canceler; const axiosToken = new axios.CancelToken((c) => { // An executor function receives a cancel function as a parameter canceler = c; }); return { cancel: (cancelMessage: any) => canceler(`Request cancelled: ${cancelMessage ?? 'User cancel'}`), token: axiosToken }; } private getRetryPolicy(retryStrategy?: RetryStrategySettings): IAxiosRetryConfig { return retryStrategy ?? this.defaultRetryStrategy; } }