admin-panel-front/src/services/api.ts
2026-08-08 10:37:44 +03:30

88 lines
2.4 KiB
TypeScript

import axios, { type AxiosError, type InternalAxiosRequestConfig } from 'axios';
import { AUTH_SCOPE } from '@/constants/auth';
import { env } from '@/config/env';
import { getAccessToken, getRefreshToken, storeAuthTokens, clearAuthTokens } from '@/utils/authToken';
import { logout } from '@/utils/logout';
import { buildAuthUrl } from '@/utils/authUrl';
import { createBasicAuthHeader } from '@/config/env';
import type { TokenResponse } from '@/types/auth';
const apiBaseUrl = env.apiBaseUrl;
const api = axios.create({
baseURL: apiBaseUrl,
timeout: 10000,
headers: {
'Content-Type': 'application/json',
},
});
let refreshPromise: Promise<void> | null = null;
api.interceptors.request.use((config) => {
const token = getAccessToken();
if (token && config.headers) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
api.interceptors.response.use(
(response) => response,
async (error: AxiosError) => {
const originalRequest = error.config as InternalAxiosRequestConfig & { _retry?: boolean };
if (!error.response || error.response.status !== 401 || originalRequest._retry) {
return Promise.reject(error);
}
if (!refreshPromise) {
refreshPromise = (async () => {
const refreshToken = getRefreshToken();
if (!refreshToken) {
throw new Error('Missing refresh token');
}
const params = new URLSearchParams();
params.append('grant_type', 'refresh_token');
params.append('refresh_token', refreshToken);
params.append('scope', AUTH_SCOPE);
const response = await axios.post<TokenResponse>(buildAuthUrl('/accounts/oauth2/token/'), params, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Authorization: createBasicAuthHeader(),
},
});
storeAuthTokens({
access_token: response.data.access_token,
refresh_token: response.data.refresh_token,
});
})().catch(() => {
clearAuthTokens();
logout();
return undefined;
});
}
try {
await refreshPromise;
originalRequest._retry = true;
const token = getAccessToken();
if (token && originalRequest.headers) {
originalRequest.headers.Authorization = `Bearer ${token}`;
}
return api(originalRequest);
} finally {
refreshPromise = null;
}
},
);
export default api;