|
|
import axios from 'axios'; |
|
|
import qs from 'qs'; |
|
|
|
|
|
const instance = axios.create({ |
|
|
baseURL: process.env.REACT_APP_API_URL || 'http://localhost:8000', |
|
|
headers: { |
|
|
'Content-Type': 'application/json', |
|
|
}, |
|
|
}); |
|
|
|
|
|
|
|
|
let isRefreshing = false; |
|
|
let failedQueue: any[] = []; |
|
|
|
|
|
const processQueue = (error: any, token: string | null = null) => { |
|
|
failedQueue.forEach(prom => { |
|
|
if (error) { |
|
|
prom.reject(error); |
|
|
} else { |
|
|
prom.resolve(token); |
|
|
} |
|
|
}); |
|
|
failedQueue = []; |
|
|
}; |
|
|
|
|
|
|
|
|
instance.interceptors.request.use( |
|
|
(config) => { |
|
|
const token = localStorage.getItem('token'); |
|
|
if (token) { |
|
|
config.headers.Authorization = `Bearer ${token}`; |
|
|
} |
|
|
|
|
|
|
|
|
if (config.data instanceof FormData) { |
|
|
config.headers['Content-Type'] = 'application/x-www-form-urlencoded'; |
|
|
config.data = qs.stringify(Object.fromEntries(config.data)); |
|
|
} |
|
|
|
|
|
return config; |
|
|
}, |
|
|
(error) => { |
|
|
return Promise.reject(error); |
|
|
} |
|
|
); |
|
|
|
|
|
|
|
|
instance.interceptors.response.use( |
|
|
(response) => response, |
|
|
async (error) => { |
|
|
const originalRequest = error.config; |
|
|
|
|
|
if (error.response?.status === 401 && !originalRequest._retry) { |
|
|
if (isRefreshing) { |
|
|
return new Promise((resolve, reject) => { |
|
|
failedQueue.push({ resolve, reject }); |
|
|
}) |
|
|
.then(token => { |
|
|
originalRequest.headers.Authorization = `Bearer ${token}`; |
|
|
return instance(originalRequest); |
|
|
}) |
|
|
.catch(err => Promise.reject(err)); |
|
|
} |
|
|
|
|
|
originalRequest._retry = true; |
|
|
isRefreshing = true; |
|
|
|
|
|
try { |
|
|
const refreshToken = localStorage.getItem('refreshToken'); |
|
|
if (!refreshToken) { |
|
|
throw new Error('No refresh token available'); |
|
|
} |
|
|
|
|
|
const response = await axios.post('/api/auth/refresh', { |
|
|
refresh_token: refreshToken, |
|
|
}); |
|
|
|
|
|
const { access_token, refresh_token } = response.data; |
|
|
localStorage.setItem('token', access_token); |
|
|
localStorage.setItem('refreshToken', refresh_token); |
|
|
|
|
|
instance.defaults.headers.common.Authorization = `Bearer ${access_token}`; |
|
|
processQueue(null, access_token); |
|
|
return instance(originalRequest); |
|
|
} catch (refreshError) { |
|
|
processQueue(refreshError, null); |
|
|
localStorage.removeItem('token'); |
|
|
localStorage.removeItem('refreshToken'); |
|
|
window.location.href = '/login'; |
|
|
return Promise.reject(refreshError); |
|
|
} finally { |
|
|
isRefreshing = false; |
|
|
} |
|
|
} |
|
|
|
|
|
return Promise.reject(error); |
|
|
} |
|
|
); |
|
|
|
|
|
|
|
|
export const handleApiError = (error: any): string => { |
|
|
if (error.response) { |
|
|
|
|
|
|
|
|
return error.response.data.message || 'An error occurred while processing your request'; |
|
|
} else if (error.request) { |
|
|
|
|
|
return 'No response received from server. Please check your internet connection'; |
|
|
} else { |
|
|
|
|
|
return error.message || 'An unexpected error occurred'; |
|
|
} |
|
|
}; |
|
|
|
|
|
export default instance; |