import axios from "axios"; const api = axios.create({ baseURL: "/api", headers: { "Content-Type": "application/json", }, }); // Attach JWT token to every request api.interceptors.request.use((config) => { const token = localStorage.getItem("access_token"); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }); // Attempt token refresh on 401 let isRefreshing = false; let pendingRequests: Array<(token: string) => void> = []; api.interceptors.response.use( (response) => response, async (error) => { const originalRequest = error.config; if (error.response?.status !== 401 || originalRequest._retry) { return Promise.reject(error); } if (isRefreshing) { return new Promise((resolve) => { pendingRequests.push((token: string) => { originalRequest.headers.Authorization = `Bearer ${token}`; resolve(api(originalRequest)); }); }); } originalRequest._retry = true; isRefreshing = true; try { const refreshToken = localStorage.getItem("refresh_token"); if (!refreshToken) { throw new Error("No refresh token"); } const { data } = await axios.post("/api/auth/token/refresh/", { refresh: refreshToken, }); localStorage.setItem("access_token", data.access); pendingRequests.forEach((cb) => cb(data.access)); pendingRequests = []; originalRequest.headers.Authorization = `Bearer ${data.access}`; return api(originalRequest); } catch { localStorage.removeItem("access_token"); localStorage.removeItem("refresh_token"); window.location.href = "/login"; return Promise.reject(error); } finally { isRefreshing = false; } } ); export default api;