import axios from "axios"; import {getCsrfToken, getSession, signOut} from "next-auth/react"; const refreshToken = async (token) => { const response = await fetch(`${process.env.API_URL}/auth/refresh`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }); const res = await response.json(); if (res.code && res.code === 401) { await signOut() return; } await updateSession(res.data) const reloadSession = () => { const event = new Event("visibilitychange"); document.dispatchEvent(event); }; if (document) reloadSession() return res.data; }; const updateSession = async (data) => { const session = await getSession(); const csrfToken = await getCsrfToken(); const updatedSessionData = { ...session, ...data}; await fetch(`${process.env.NEXTAUTH_URL}/api/auth/session`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ csrfToken: csrfToken, data: { ...updatedSessionData } }) }); }; let isRefreshing = false; let refreshAndRetryQueue = [] const Api = () => { const instance = axios.create({ baseURL: process.env.API_URL }) instance.interceptors.request.use(async (request) => { const session = await getSession(); if (session && session.user) { request.headers.Authorization = `Bearer ${session.token}`; } return request; }); instance.interceptors.response.use( (response) => response, async (error) => { const originalRequest = error.config; const session = await getSession(); if (error?.response?.status === 401 && session && session.user) { if (!isRefreshing) { isRefreshing = true try { const data = await refreshToken(session.refresh_token); originalRequest.headers.Authorization = `Bearer ${data.token}`; refreshAndRetryQueue.forEach(({ config, resolve, reject }) => { instance.request(config) .then(response => resolve(response)) .catch(err => reject(err)) }) refreshAndRetryQueue.length = 0 return axios(originalRequest); }catch (e) { console.log(e) }finally { isRefreshing = false } } return new Promise((resolve, reject) => { refreshAndRetryQueue.push({config: originalRequest, resolve, reject}) }) } return Promise.reject(error); } ); return instance } export default Api()