import { getConfigApp } from '@/utils/config' import { baseURL as fallbackBaseURL } from '@/themeConfig' import type {AxiosRequestConfig, AxiosResponse} from 'axios' import axios from 'axios' import {getToken, removeToken} from "@/utils"; import router from "@/router"; import {get} from 'lodash' import {message} from "ant-design-vue"; interface Meta { errorMessage?: 'message' | 'notification' | 'toast' | 'none' } interface MyAxiosRequestConfig extends AxiosRequestConfig { meta?: Meta } const headers = { 'Content-Type': 'application/json', Accept: 'application/json', } const _axios = axios.create({ baseURL: fallbackBaseURL, headers, }) _axios.interceptors.request.use( (config) => { const runtimeBaseURL = getConfigApp('node_server') if (runtimeBaseURL) { config.baseURL = runtimeBaseURL } //console.log('request config', config) if (config.headers) { const token = getToken() if (token) { //@ts-ignore config.headers['Authorization'] = 'Bearer ' + token } } return config }, (error) => { //console.log('this is error on interceptors.request', error) Promise.reject(error) }, ) _axios.interceptors.response.use( (response) => { //console.log('this is response') // Any status code that lie within the range of 2xx cause this function to trigger // Do something with response data //console.log('this is fulfilled on interceptors.response', response.data) return response.data }, async function (error) { const response = error.response const config = error.config as MyAxiosRequestConfig | undefined if (response?.status === 401) { removeToken() showPleaseLoginAgain() const routeName = router.currentRoute.value.name const isPublicRoute = router.currentRoute.value.meta?.public === true || ['buyProduct', 'productDetail', 'about', 'cart', 'tvMonitor', 'login', '404'].includes( routeName as string, ) if (!isPublicRoute) { await router.push({name: 'login'}) } return Promise.reject(error) } if (!shouldShowApiError(config)) { return Promise.reject(error) } const apiMessage = extractApiErrorMessage(response?.data) const status = Number(response?.status ?? 0) if (response?.status === 403) { showApiError( withHttpStatus(apiMessage || 'شما دسترسی لازم برای انجام این عملیات را ندارید', 403), config, ) return Promise.reject(error) } if (response?.status === 422) { if (apiMessage) { showApiError(withHttpStatus(apiMessage, 422), config) } else { showApiError(withHttpStatus('خطا در اعتبارسنجی', 422), config) } return Promise.reject(error) } if (response) { if (status >= 500) { showApiError(withHttpStatus(SERVER_ERROR, status), config) } else { showApiError(withHttpStatus(apiMessage || DEFAULT_LOAD_ERROR, status), config) } return Promise.reject(error) } // بدون status (نه 4xx نه 5xx): قطع شبکه، timeout، DNS، … showApiError(NETWORK_ERROR, config) return Promise.reject(error) }) const DEFAULT_LOAD_ERROR = 'خطا در بارگذاری اطلاعات' const SERVER_ERROR = 'خطا در برقراری ارتباط با سرور' const NETWORK_ERROR = 'لطفا اینترنت خود را بررسی کنید و مجددا تلاش کنید' const LOGIN_AGAIN = 'لطفا مجددا وارد شوید' let lastAuthToastAt = 0 function showPleaseLoginAgain() { const now = Date.now() if (now - lastAuthToastAt < 2500) return lastAuthToastAt = now message.error({ content: LOGIN_AGAIN, key: 'please-login-again', duration: 3, }) } function withHttpStatus(message: string, status: number): string { return `${message} (${status})` } function extractApiErrorMessage(data: unknown): string { if (!data || typeof data !== 'object') { return '' } const record = data as Record const rawMessage = record.message if (typeof rawMessage === 'string' && rawMessage.trim()) { return rawMessage.trim() } if (typeof rawMessage === 'number') { return String(rawMessage) } const rawError = record.error if (typeof rawError === 'string' && rawError.trim()) { return rawError.trim() } const errors = record.errors if (errors && typeof errors === 'object') { for (const value of Object.values(errors as Record)) { if (Array.isArray(value) && typeof value[0] === 'string' && value[0].trim()) { return value[0].trim() } if (typeof value === 'string' && value.trim()) { return value.trim() } } } return '' } function shouldShowApiError(config: MyAxiosRequestConfig | undefined): boolean { return get(config, 'meta.errorMessage', 'message') !== 'none' } function showApiError(msg: string, config: MyAxiosRequestConfig | undefined) { if (!shouldShowApiError(config)) { return } message.error(msg) } const myAxios = { //AxiosResponse post( url: string, data?: D, config?: MyAxiosRequestConfig, ): Promise { return _axios.post(url, data, config) }, request, D = any>(config: MyAxiosRequestConfig): Promise { return _axios.request(config) }, //AxiosResponse get(url: string, config?: MyAxiosRequestConfig): Promise { return _axios.get(url, config) }, //AxiosResponse delete(url: string, config?: MyAxiosRequestConfig): Promise { return _axios.delete(url, config) }, //AxiosResponse head(url: string, config?: MyAxiosRequestConfig): Promise { return _axios.head(url, config) }, //AxiosResponse options(url: string, config?: MyAxiosRequestConfig): Promise { return _axios.options(url, config) }, //AxiosResponse put( url: string, data?: D, config?: MyAxiosRequestConfig, ): Promise { return _axios.put(url, data, config) }, //AxiosResponse patch( url: string, data?: D, config?: MyAxiosRequestConfig, ): Promise { return _axios.patch(url, data, config) }, //AxiosResponse postForm( url: string, data?: D, config?: MyAxiosRequestConfig, ): Promise { return _axios.postForm(url, data, config) }, //AxiosResponse putForm( url: string, data?: D, config?: MyAxiosRequestConfig, ): Promise { return _axios.putForm(url, data, config) }, //AxiosResponse patchForm( url: string, data?: D, config?: MyAxiosRequestConfig, ): Promise { return _axios.patchForm(url, data, config) }, } export default myAxios export {_axios}