import axios, { AxiosError, AxiosResponse, InternalAxiosRequestConfig } from 'axios'; import { WHITE_LIST_URLS } from '@/shared/api/urls'; import { StorageKeys } from '@/shared/constants/local-storage'; import { checkIsAxiosError, getLocalStorage, setLocalStorage, snackBar } from '@/shared/lib'; import { appBridge } from '@/utils/appBridge'; import { LoginResponse } from '@/entities/user/model/types'; import { getHeaderUserAgent } from '@/shared/constants/url'; import { useAppBridge } from '@/hooks'; import { useUserInfo } from '@/entities/user/lib/use-user-info'; import { useStore } from '@/shared/model/store'; import { login } from '@/entities/user/api/use-login-mutation'; import { useNavigate } from '@/shared/lib/hooks'; const finalizeConfig = (config: InternalAxiosRequestConfig) => { const { params, data } = config; return { ...config, params, data, }; }; const onRequestFulfilled = (config: InternalAxiosRequestConfig) => { config.headers['Content-Type'] = 'application/json;charset=UTF-8'; if(!config.headers['X-User-Agent']){ config.headers['X-User-Agent'] = getHeaderUserAgent(); } if(WHITE_LIST_URLS.includes(config?.url ?? '')){ if(config.headers.hasOwnProperty('Authorization')){ delete config.headers.Authorization; } } else{ const accessToken = getLocalStorage(StorageKeys.AccessToken); const tokenType = getLocalStorage(StorageKeys.TokenType); config.headers.Authorization = `${tokenType} ${accessToken}`; } return finalizeConfig(config); }; const onRequestRejected = (error: any) => { console.log('onRequestRejected --> ', error); return Promise.reject(error); }; const onResponseFulfilled = (response: AxiosResponse) => { return { ...response, data: response.data.data || response.data, }; }; const onResponseRejected = (error: AxiosError) => { console.log('onResponseRejected --> ', error); if(!!error.code && error.code === 'ETIMEDOUT'){ snackBar(error?.message); } if(error?.status === 401){ if(appBridge.isNativeEnvironment()){ return appBridge.safeCall(() => appBridge.requestRefreshToken()).then((token: LoginResponse) => { setLocalStorage(StorageKeys.TokenType, token.tokenType); setLocalStorage(StorageKeys.AccessToken, token.accessToken); setLocalStorage(StorageKeys.RefreshToken, token.refreshToken); setLocalStorage(StorageKeys.AccessTokenExpiresIn, token.accessTokenExpiresIn); setLocalStorage(StorageKeys.RefreshTokenExpiresIn, token.refreshTokenExpiresIn); setLocalStorage(StorageKeys.MenuGrants, token.menuGrants); setLocalStorage(StorageKeys.ClientAddressIP, token.clientAddressIP); setLocalStorage(StorageKeys.Requires2FA, token.requires2FA); setLocalStorage(StorageKeys.Usrid, token.usrid); if(appBridge.isNativeEnvironment()){ setLocalStorage(StorageKeys.DeviceId, token.deviceId); setLocalStorage(StorageKeys.AppVersion, token.appVersion); } useStore.getState().UserStore.setUserInfo({ ...token }); return error.config? axios.request(error.config): null; }); } else{ let params = { // id: 'woowahan5', id: 'nictest00', password: 'nictest00' }; return login(params).then((result: LoginResponse) => { setLocalStorage(StorageKeys.TokenType, result.tokenType); setLocalStorage(StorageKeys.AccessToken, result.accessToken); setLocalStorage(StorageKeys.RefreshToken, result.refreshToken); setLocalStorage(StorageKeys.AccessTokenExpiresIn, result.accessTokenExpiresIn); setLocalStorage(StorageKeys.RefreshTokenExpiresIn, result.refreshTokenExpiresIn); setLocalStorage(StorageKeys.MenuGrants, result.menuGrants); setLocalStorage(StorageKeys.ClientAddressIP, result.clientAddressIP); setLocalStorage(StorageKeys.Requires2FA, result.requires2FA); setLocalStorage(StorageKeys.Usrid, params.id); if(appBridge.isNativeEnvironment()){ setLocalStorage(StorageKeys.DeviceId, result.deviceId); setLocalStorage(StorageKeys.AppVersion, result.appVersion); } useStore.getState().UserStore.setUserInfo({ ...result }); return error.config? axios.request(error.config): null; }); } } return new Promise((_resolve, reject) => { if(checkIsAxiosError(error)){ // iOS의 경우 window에서 unload event가 일어날때 네트워크 에러가 발생하곤 해서 이런 케이스를 방지하기 위해 지연시킴 // location.href, location.reload 등으로 unload event가 일어나면 자바스크립트 런타임이 초기화되므로 settimeout으로 인한 네트워크 에러가 트리거 x setTimeout(() => { reject(error); }, 300); } else{ reject(error); } }); }; export const initAxios = () => { axios.defaults.withCredentials = false; axios.defaults.timeout = 60000; axios.defaults.transitional = { clarifyTimeoutError: true, forcedJSONParsing: true, silentJSONParsing: true, }; axios.interceptors.request.use(onRequestFulfilled, onRequestRejected); axios.interceptors.response.use(onResponseFulfilled, onResponseRejected); };