117 lines
3.1 KiB
TypeScript
117 lines
3.1 KiB
TypeScript
import i18n from "@/shared/config/i18n";
|
|
import {
|
|
getAuthToken,
|
|
getRefAuthToken,
|
|
removeAuthToken,
|
|
removeRefAuthToken,
|
|
setAuthToken,
|
|
} from "@/shared/lib/authCookies";
|
|
import axios, { AxiosError } from "axios";
|
|
import { BASE_URL } from "./URLs";
|
|
|
|
let isRefreshing = false;
|
|
let failedQueue: {
|
|
resolve: (token: string) => void;
|
|
reject: (error: any) => void;
|
|
}[] = [];
|
|
|
|
const processQueue = (error: any, token: string | null = null) => {
|
|
failedQueue.forEach((prom) => {
|
|
if (error) prom.reject(error);
|
|
else if (token) prom.resolve(token);
|
|
});
|
|
failedQueue = [];
|
|
};
|
|
|
|
const httpClient = axios.create({
|
|
baseURL: BASE_URL,
|
|
timeout: 10000,
|
|
});
|
|
|
|
httpClient.interceptors.request.use(
|
|
async (config) => {
|
|
const method: string = (config.method || "").toLowerCase();
|
|
|
|
if (method === "get") {
|
|
// GET so'rovlarda hozirgi i18n tilini yuboramiz
|
|
config.headers["Accept-Language"] = i18n.language;
|
|
} else if (["put", "post", "delete"].includes(method)) {
|
|
// PUT, POST, DELETE da faqat "uz"
|
|
config.headers["Accept-Language"] = "uz";
|
|
}
|
|
|
|
const accessToken = getAuthToken();
|
|
if (accessToken) {
|
|
config.headers["Authorization"] = `Bearer ${accessToken}`;
|
|
}
|
|
|
|
return config;
|
|
},
|
|
(error) => Promise.reject(error),
|
|
);
|
|
|
|
httpClient.interceptors.response.use(
|
|
(response) => response,
|
|
async (error: AxiosError) => {
|
|
const originalRequest = error.config as any;
|
|
|
|
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 httpClient(originalRequest);
|
|
})
|
|
.catch((err) => Promise.reject(err));
|
|
}
|
|
|
|
originalRequest._retry = true;
|
|
isRefreshing = true;
|
|
|
|
const refreshToken = getRefAuthToken();
|
|
if (!refreshToken) {
|
|
removeAuthToken();
|
|
removeRefAuthToken();
|
|
window.location.href = "/login";
|
|
return Promise.reject(error);
|
|
}
|
|
|
|
try {
|
|
const response = await axios.post(`${BASE_URL}auth/token/refresh/`, {
|
|
refresh: refreshToken,
|
|
});
|
|
|
|
const newAccessToken = response.data.access;
|
|
setAuthToken(newAccessToken);
|
|
|
|
httpClient.defaults.headers["Authorization"] =
|
|
`Bearer ${newAccessToken}`;
|
|
processQueue(null, newAccessToken);
|
|
|
|
originalRequest.headers["Authorization"] = `Bearer ${newAccessToken}`;
|
|
return httpClient(originalRequest);
|
|
} catch (refreshError: any) {
|
|
processQueue(refreshError, null);
|
|
removeAuthToken();
|
|
removeRefAuthToken();
|
|
const status = refreshError.response?.status;
|
|
|
|
if ([401].includes(status)) {
|
|
window.location.href = "/login";
|
|
}
|
|
|
|
return Promise.reject(refreshError);
|
|
} finally {
|
|
isRefreshing = false;
|
|
}
|
|
}
|
|
|
|
console.error("API error:", error);
|
|
return Promise.reject(error);
|
|
},
|
|
);
|
|
|
|
export default httpClient;
|