/
zkuzmine
/
SheduleHelperFront
Обзор
Документация
Войти
/
zkuzmine
/
SheduleHelperFront
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/api/client.js
105 строк
3 KB
zkuzmine-dot
bug fixing
17 июн 2026, 16:44
17 июн 2026, 16:44
081a8b1
Код
Авторство
О чём код?
import axios from 'axios'; // Базовый URL бэкенда const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'https://timeofthestars.online'; // Создаем axios instance const apiClient = axios.create({ baseURL: API_BASE_URL, headers: { 'Content-Type': 'application/json', }, }); // Флаг, чтобы не создавать множество refresh-запросов одновременно let isRefreshing = false; let failedQueue = []; const processQueue = (error, token = null) => { failedQueue.forEach(prom => { if (error) { prom.reject(error); } else { prom.resolve(token); } }); isRefreshing = false; failedQueue = []; }; // Interceptor для добавления access token в каждый запрос apiClient.interceptors.request.use( (config) => { const token = localStorage.getItem('accessToken'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }, (error) => Promise.reject(error) ); // Interceptor для обработки ошибок и автоматического refresh // Эндпоинты авторизации — 401 здесь означает "неверные данные", а не "сессия истекла" const AUTH_ENDPOINTS = ['/token', '/token/telegram', '/refresh']; apiClient.interceptors.response.use( (response) => response, async (error) => { const originalRequest = error.config; const isAuthEndpoint = AUTH_ENDPOINTS.some((path) => originalRequest?.url?.includes(path)); // Если 401 и еще не пытались refresh (и это не сам запрос логина/рефреша) if (error.response?.status === 401 && !originalRequest._retry && !isAuthEndpoint) { if (isRefreshing) { // Ждем, пока текущий refresh завершится return new Promise((resolve, reject) => { failedQueue.push({ resolve: (token) => { originalRequest.headers.Authorization = `Bearer ${token}`; resolve(apiClient(originalRequest)); }, reject, }); }); } originalRequest._retry = true; isRefreshing = true; try { const refreshToken = localStorage.getItem('refreshToken'); if (!refreshToken) { throw new Error('No refresh token'); } const response = await axios.post(`${API_BASE_URL}/refresh`, { refresh_token: refreshToken, }); const { access_token, refresh_token } = response.data; localStorage.setItem('accessToken', access_token); localStorage.setItem('refreshToken', refresh_token); apiClient.defaults.headers.common.Authorization = `Bearer ${access_token}`; originalRequest.headers.Authorization = `Bearer ${access_token}`; processQueue(null, access_token); return apiClient(originalRequest); } catch (err) { processQueue(err, null); // Logout на ошибку refresh localStorage.removeItem('accessToken'); localStorage.removeItem('refreshToken'); window.location.href = '/login'; return Promise.reject(err); } } return Promise.reject(error); } ); export default apiClient;