With the following code, it's work on almost all my pages except one where I load many tabs in same time (eager tab on vuetify2)
expected:
- send http request
- if response is 401 (token is expired) we get a new fresh token and rerty all request with new token.
- if response is 200, continue
But in this page I get:
- send http request
- get 10 response 401 (9 response to 10:15:10 and 1 to 10:15:11) (1 seconde)
- get fresh token and remake 9 request
- get fresh token again and remake other request
Why the last request dont use the same token ? How can I do to avoid to create a new token again if the old is valid)
let isTokenRefreshing = false;
let subscribers = [];
let refreshTokenPromise = null; // Nous allons utiliser cette variable pour partager la promesse de rafraîchissement du token entre toutes les requêtes.
function onTokenRefreshed(token) {
console.log("Token refreshed:", token);
// Relance toutes les requêtes qui attendaient le token
subscribers.forEach(callback => callback(token));
subscribers = []; // Vide la file d'attente
}
function subscribeToTokenRefresh(callback) {
console.log("Nouvelle requête ajoutée à la file d'attente.");
subscribers.push(callback); // Ajoute les callbacks dans la file d'attente
}
window.axios.interceptors.response.use(
response => response, // Si la réponse est OK, on la retourne
async error => {
const originalRequest = error.config;
// Vérifie si c'est bien une erreur 401 et que la requête n'a pas déjà été retentée
if (error.response && error.response.status === 401 && !originalRequest._retry) {
console.log("401 détectée, tentative de rafraîchissement du token.");
// Si le token est déjà en cours de récupération, on attend
if (refreshTokenPromise) {
console.log("Le rafraîchissement du token est déjà en cours, on attend...");
return new Promise((resolve, reject) => {
subscribeToTokenRefresh(token => {
originalRequest.headers['Authorization'] = `Bearer ${token}`; // Mets à jour l'en-tête pour cette requête
resolve(axios(originalRequest)); // Relance la requête d'origine avec le nouveau token
});
});
}
console.log("Détails de la requête originale qui a échoué avec 401 :");
console.log("URL de la requête:", originalRequest.url);
console.log("Méthode de la requête:", originalRequest.method);
console.log("Headers de la requête:", originalRequest.headers);
// Marque cette requête comme étant en cours de réessai
originalRequest._retry = true;
console.log("Démarrage du rafraîchissement du token...");
// Si ce n'est pas encore fait, on initialise la promesse de rafraîchissement du token
refreshTokenPromise = axios.post('/api/refresh-token') // Remplacez cette URL par votre API de rafraîchissement de token
.then(response => {
const newToken = response.data.token;
console.log("Nouveau token récupéré :", newToken);
// Sauvegarde du nouveau token (par exemple, dans localStorage, Vuex, etc.)
localStorage.setItem('UserToken', newToken);
const user = {
isLoggedIn: true,
user: response.data.user
};
localStorage.setItem('User', JSON.stringify(user));
// On relance toutes les requêtes qui attendaient
onTokenRefreshed(newToken);
// Retourne le nouveau token
return newToken;
})
.catch(err => {
console.error("Erreur lors du rafraîchissement du token :", err);
return Promise.reject(err);
})
.finally(() => {
// Réinitialise la promesse de rafraîchissement du token
refreshTokenPromise = null;
});
// Maintenant on attend que la promesse de rafraîchissement se termine
const newToken = await refreshTokenPromise;
// Relance la requête initiale avec le nouveau token
originalRequest.headers['Authorization'] = `Bearer ${newToken}`;
return axios(originalRequest);
}
return Promise.reject(error); // Autres erreurs, on les passe
}
);