This commit is contained in:
javad committed 2026-10-08 20:26:47 +03:30
1 parent b4fbb93ab5
commit 4d350c0278
11 files changed
+1082 -295

No files matched your search

+54 -78
View File
@@ -1,88 +1,64 @@
'use client'
import axios from 'axios'
import { error } from 'console';
import { cookies, headers } from 'next/headers'
import axios, { AxiosError, InternalAxiosRequestConfig } from 'axios'
import { expireSession, getAccessToken, getRefreshToken, saveTokens } from '@/lib/auth'
//let accessToken = localStorage.getItem('access') ? localStorage.getItem('access') : null
function setCookieFn(name:string, value:string, daysToExpire:number) {
const expires = new Date();
expires.setTime(expires.getTime() + (daysToExpire * 24 * 60 * 60 * 1000));
document.cookie = `${name}=${value};expires=${expires.toUTCString()};path=/`;
}
type RetryRequest = InternalAxiosRequestConfig & { _retry?: boolean }
class InvalidSession extends Error {}
let pendingRefresh: Promise<string> | null = null
const axiosInstance = axios.create({
baseURL: `${process.env.NEXT_PUBLIC_API_URL}/`,
timeout: 2000,
headers: {
'Content-Type': 'application/json',
//'Authorization': `Bearer ${accessToken}`,
}
});
axiosInstance.interceptors.request.use(async req => {
const accessT = await localStorage.getItem('access')
req.headers.Authorization = `Bearer ${accessT}`
return req
baseURL: process.env.NEXT_PUBLIC_API_URL + '/',
timeout: 10000,
headers: { 'Content-Type': 'application/json' },
})
axiosInstance.interceptors.response.use((response)=> {
return response
}, async (error) =>{
axiosInstance.interceptors.request.use(request => {
const access = getAccessToken()
if (access) request.headers.Authorization = 'Bearer ' + access
else delete request.headers.Authorization
return request
})
const originalRequest = error.config;
if (error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true; // Prevent infinite loops
try {
if (localStorage.getItem('refresh') != 'undefined'){
const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/auth/token/refresh/`, {
method: "POST",
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: JSON.stringify({
'refresh': localStorage.getItem('refresh')
})
});
if(res.status==200){
setCookieFn('isAuth', 'true', 365)
const tokenData = await res.json()
localStorage.setItem('access', tokenData.access)
localStorage.setItem('refresh',tokenData.refresh)
originalRequest.headers.Authorization = `Bearer ${tokenData.access}`
return axiosInstance(originalRequest)
}else{
}
} else {
localStorage.removeItem('access');
localStorage.removeItem('refresh');
document.cookie = "isAuth=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
setTimeout(()=>{
window.location.replace('/login')
}, 200)
}
} catch(refreshError) {
localStorage.removeItem('access');
localStorage.removeItem('refresh');
document.cookie = "isAuth=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
setTimeout(()=>{
window.location.replace('/login')
}, 200)
throw refreshError;
}
async function refreshAccess(): Promise<string> {
const refresh = getRefreshToken()
if (!refresh) throw new InvalidSession()
try {
const response = await axios.post(process.env.NEXT_PUBLIC_API_URL + '/auth/token/refresh/', { refresh }, { timeout: 10000 })
if (getRefreshToken() !== refresh) throw new Error('نشست تغییر کرده است.')
if (!response.data?.access || !response.data?.refresh) throw new InvalidSession()
saveTokens(response.data)
return response.data.access
} catch (error) {
if (axios.isAxiosError(error) && [400, 401, 403].includes(error.response?.status || 0)) throw new InvalidSession()
throw error
}
});
}
export default axiosInstance
axiosInstance.interceptors.response.use(response => response, async (error: AxiosError) => {
const request = error.config as RetryRequest | undefined
if (error.response?.status !== 401 || !request || /\/auth\//.test(request.url || '')) return Promise.reject(error)
if (request._retry) {
const latest = getAccessToken()
if (!latest || request.headers.Authorization === 'Bearer ' + latest) expireSession()
return Promise.reject(error)
}
request._retry = true
// Another request may already have refreshed the token that this request used.
const currentAccess = getAccessToken()
if (currentAccess && request.headers.Authorization !== 'Bearer ' + currentAccess) {
request.headers.Authorization = 'Bearer ' + currentAccess
return axiosInstance(request)
}
const refresh = getRefreshToken()
try {
if (!pendingRefresh) pendingRefresh = refreshAccess().finally(() => { pendingRefresh = null })
request.headers.Authorization = 'Bearer ' + await pendingRefresh
return axiosInstance(request)
} catch (refreshError) {
if (refreshError instanceof InvalidSession && getRefreshToken() === refresh) expireSession()
return Promise.reject(refreshError)
}
})
export default axiosInstance