Я использую перехватчик Axios, чтобы получить новый токен доступа с токеном обновления. Следующий код создает новый токен доступа с сервера, но я не могу найти файл cookie в браузере.
Работает нормально, но браузер глючит при загрузке.
Было бы очень полезно, если бы кто-нибудь нашел, в чем проблема.
Заранее спасибо.
interface RetryQueueItem {
resolve: (value?: any) => void;
reject: (error?: any) => void;
config: AxiosRequestConfig;
}
const fetchAxiosClient: AxiosInstance = axios.create({
baseURL: 'http://localhost:8080/api/v1',
timeout: 60000
});
fetchAxiosClient.defaults.headers.common = {
'Content-Type': 'application/json',
'Accept': 'application/json'
} as headers;
export async function createAxiosInstance(requestEvent) {
// Auth token to request header
fetchAxiosClient.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
const token = getAccessToken(requestEvent.cookieObj).access_token;
if (token) {
config.headers['Authorization'] = `Bearer ${token}`;
}
config.headers['Content-Type'] = 'application/json';
return config;
},
error => Promise.reject(error)
);
const refreshAndRetryQueue: RetryQueueItem[] = [];
let isRefreshing = false;
fetchAxiosClient.interceptors.response.use(
function (response: AxiosResponse) {
return response;
},
async function (error: any) {
const originalRequest: AxiosRequestConfig = error.config;
if (error.response && error.response.status === 401) {
if (!isRefreshing) {
isRefreshing = true;
try {
const refreshToken = getRefreshToken(requestEvent.cookieObj);
if (refreshToken) {
await axios.post(
`${fetchAxiosClient?.defaults.baseURL}${REFRESH_TOKEN}`,
{
refresh_token: refreshToken,
}
).then(async (response: any) => {
const cookies = response.headers['set-cookie'] as string[];
const accessToken = getToken(cookies[0], APP_CONSTANTS.ACCESS_TOKEN);
setToken(requestEvent.cookieObj, accessToken!);
return fetchAxiosClient!(originalRequest);
}).catch((error) => {
requestEvent.cookieObj.delete(APP_CONSTANTS.ACCESS_TOKEN, { path: '/' });
throw requestEvent.redirect(302, '/login');
//return Promise.reject(error);
});
refreshAndRetryQueue.forEach(({ config, resolve, reject }) => {
fetchAxiosClient!(config)
.then((response) => resolve(response))
.catch((err) => reject(err));
});
refreshAndRetryQueue.length = 0;
} else {
requestEvent.cookieObj.delete(APP_CONSTANTS.ACCESS_TOKEN, { path: '/' });
window.location.href = "/";
return Promise.reject(error);
}
} catch (refreshError) {
refreshAndRetryQueue.length = 0;
requestEvent.cookieObj.delete(APP_CONSTANTS.ACCESS_TOKEN, { path: '/' });
} finally {
isRefreshing = false;
}
}
return new Promise<void>((resolve, reject) => {
refreshAndRetryQueue.push({ config: originalRequest, resolve, reject });
});
}
return Promise.reject(error);
}
);
}
Новый сгенерированный токен доступа, срок действия которого истечет через 15 минут, должен быть установлен как файл cookie. В момент истечения срока действия токена доступа новый токен доступа должен быть сгенерирован с токеном обновления.
Но после истечения срока действия токена доступа при создании нового токена доступа браузер показывает индикатор загрузки и постоянно занят.
🤔 А знаете ли вы, что...
React поддерживает создание контролируемых и неконтролируемых компонентов форм.
Логика кода выглядит запутанной. Используйте этот плагин, чтобы упростить ваш код:
https://github.com/Flyrell/axios-auth-refresh
я это упомянул
работает нормально.
export async function createAxiosInstance(cookieObj: Cookie) {
interface FailedRequests {
resolve: (value: AxiosResponse) => void;
reject: (value: AxiosError) => void;
config: AxiosRequestConfig;
error: AxiosError;
}
// Add the auth token to every request
fetchAxiosClient.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
const token = getAccessToken(cookieObj).access_token;
if (token) {
config.headers['Authorization'] = `Bearer ${token}`;
}
config.headers['Content-Type'] = 'application/json';
return config;
},
error => Promise.reject(error)
);
let failedRequests: FailedRequests[] = [];
let isTokenRefreshing = false;
fetchAxiosClient.interceptors.response.use(
function (response: AxiosResponse) {
return response;
},
async (error: AxiosError) => {
const status = error.response?.status;
const originalRequestConfig = error.config!;
if (status !== 401) {
return Promise.reject(error);
}
if (isTokenRefreshing) {
return new Promise((resolve, reject) => {
failedRequests.push({
resolve,
reject,
config: originalRequestConfig,
error: error,
});
});
}
isTokenRefreshing = true;
const refreshToken = getRefreshToken(cookieObj);
try {
const response = await fetchAxiosClient.post(
`${fetchAxiosClient?.defaults.baseURL}${REFRESH_TOKEN}`,
{
refresh_token: refreshToken,
}
);
const cookies = response.headers['set-cookie'] as string[];
const accessToken = getToken(cookies[0], APP_CONSTANTS.ACCESS_TOKEN);
setToken(cookieObj, accessToken!);
failedRequests.forEach(({ resolve, reject, config }) => {
fetchAxiosClient(config)
.then((response) => resolve(response))
.catch((error) => reject(error));
});
} catch (_error: unknown) {
console.error(_error);
failedRequests.forEach(({ reject, error }) => reject(error));
cookieObj.delete(APP_CONSTANTS.ACCESS_TOKEN, { path: '/' });
return Promise.reject(error);
} finally {
failedRequests = [];
isTokenRefreshing = false;
}
return fetchAxiosClient(originalRequestConfig);
}
);
}