import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios' import axiosRetry from 'axios-retry' import { HttpProxyAgent } from 'http-proxy-agent' import { HttpsProxyAgent } from 'https-proxy-agent' import { URL } from 'url' import type { AccountProxy } from '../interface/Account' class AxiosClient { private instance: AxiosInstance private account: AccountProxy constructor(account: AccountProxy) { this.account = account this.instance = axios.create({ timeout: 20000 }) if (this.account.url && this.account.proxyAxios) { const agent = this.getAgentForProxy(this.account) this.instance.defaults.httpAgent = agent this.instance.defaults.httpsAgent = agent } axiosRetry(this.instance, { retries: 5, retryDelay: axiosRetry.exponentialDelay, shouldResetTimeout: true, retryCondition: error => { if (axiosRetry.isNetworkError(error)) return true if (!error.response) return true const status = error.response.status return status === 429 || (status >= 500 && status <= 599) } }) } private getAgentForProxy(proxyConfig: AccountProxy): HttpProxyAgent | HttpsProxyAgent { const { url: baseUrl, port, username, password } = proxyConfig let urlObj: URL try { urlObj = new URL(baseUrl) } catch (e) { try { urlObj = new URL(`http://${baseUrl}`) } catch (error) { throw new Error(`Invalid proxy URL format: ${baseUrl}`) } } const protocol = urlObj.protocol.toLowerCase() let proxyUrl: string if (username && password) { urlObj.username = encodeURIComponent(username) urlObj.password = encodeURIComponent(password) urlObj.port = port.toString() proxyUrl = urlObj.toString() } else { proxyUrl = `${protocol}//${urlObj.hostname}:${port}` } switch (protocol) { case 'http:': return new HttpProxyAgent(proxyUrl) case 'https:': return new HttpsProxyAgent(proxyUrl) default: throw new Error(`Unsupported proxy protocol: ${protocol}. Only HTTP(S) is supported!`) } } public async request(config: AxiosRequestConfig, bypassProxy = false): Promise { if (bypassProxy) { const bypassInstance = axios.create() axiosRetry(bypassInstance, { retries: 3, retryDelay: axiosRetry.exponentialDelay }) return bypassInstance.request(config) } return this.instance.request(config) } } export default AxiosClient