Я использую Axios во внешнем интерфейсе моего проекта, и мне нужен был способ перенаправить пользователя на страницу входа, если он хочет использовать токены с истекшим сроком действия (токен обновления недопустим для бэкэнда), я обнаружил шаблонный код в сети, который выглядел достаточно простым для адаптации к моему техническому стеку (ReactJS без Redux):
import axios from 'axios';
// additional code that lives in its own module
const getToken = () => {
return isAuth() ? window.localStorage.getItem("token") : "";
};
const getRefreshToken = () => {
return isAuth() ? window.localStorage.getItem("refresh_token") : "";
};
const setTokens = (token, refresh) => {
window.localStorage.setItem("token", token);
window.localStorage.setItem("refresh_token", refresh);
};
// this is on my app.js file
axios.interceptors.response.use(function (response) {
return response;
}, function (error) {
const originalRequest = error.config;
if (error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
// Hace la solicitud de refresco de tokens
return axios.get('/api/v1/auth', {headers: {'Authorization': 'Bearer ' + getRefreshToken()}})
.then((responseData) => {
// actualiza la información de OAuth
setTokens(responseData.data.access_token, responseData.data.refresh_token);
axios.defaults.headers.common['Authorization'] = 'Bearer ' + getToken();
originalRequest.headers['Authorization'] = 'Bearer ' + getToken();
// re-intenta la solicitud original
return axios(originalRequest);
}).catch(function (error) {
console.log(error);
setTokens(undefined, undefined);
window.location.pathname = "/login";
});
}
return Promise.reject(error);
});
Проблема заключается в том, что код входит в бесконечную рекурсию, оставляя интерфейс непригодным для использования,если я перехожу на /login
вручную, рекурсия полностью прекращается.
РЕДАКТИРОВАТЬ
Вот весь исходный код файла, в котором я только что должен был внести изменения в соответствии с решением, принятым для моеговопрос:
import React, { Component } from 'react';
import createHistory from 'history/createBrowserHistory';
import {Router} from 'react-router';
import Fero from './containers/Fero/Fero';
import {setTokens, getRefreshToken, getToken} from './utils/auth';
import axios from 'axios';
const myhistory = createHistory();
axios.interceptors.response.use(function (response) {
return response;
}, function (error) {
const originalRequest = error.config;
if (error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
// Hace la solicitud de refresco de tokens
return axios.get('/api/v1/auth', {headers: {'Authorization': 'Bearer ' + getRefreshToken()}})
.then((responseData) => {
// actualiza la información de OAuth
setTokens(responseData.data.access_token, responseData.data.refresh_token);
axios.defaults.headers.common['Authorization'] = 'Bearer ' + getToken();
originalRequest.headers['Authorization'] = 'Bearer ' + getToken();
// re-intenta la solicitud original
return axios(originalRequest);
}).catch(function (error) {
console.log(error);
setTokens(undefined, undefined);
myhistory.replace("/login");
});
}
return Promise.reject(error);
});
class App extends Component {
render() {
return (
<Router history={myhistory}>
<Fero/>
</Router>
);
}
}
export default App;