Created
February 22, 2022 17:45
-
-
Save CryceTruly/31cdc3c7b06b032dad4302590a390ad0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import AsyncStorage from '@react-native-async-storage/async-storage'; | |
import axios, {AxiosError} from 'axios'; | |
import {logOutUserLocal} from 'redux/actions/auth/logout/clearAllUser'; | |
import store from 'redux/store'; | |
import envs from 'config/env'; | |
// Getting token from local Storage | |
async function getLocalToken() { | |
const token = await AsyncStorage.getItem('token'); | |
return `Bearer ${token}`; | |
} | |
// Add a setToken method to the instance to dynamically add the latest token to the header after login, and save the token in the local Storage | |
const setNewToken = (token: string) => { | |
instance.defaults.headers.Authorization = `Bearer ${token}`; | |
AsyncStorage.setItem('token', token); | |
}; | |
async function refreshToken() { | |
// Instance is the axios instance created in current request.js | |
const token = await AsyncStorage.getItem('refresh_token'); | |
const res = await instance.post('/auth/token/refresh/', { | |
refresh: token, | |
}); | |
return res.data.access; | |
} | |
// Create an axios instance | |
const instance = axios.create({ | |
baseURL: envs.BACKEND_URL, | |
headers: { | |
'Content-Type': 'application/json', | |
Authorization: getLocalToken(), // headers settoken | |
}, | |
}); | |
instance.interceptors.request.use( | |
async config => { | |
const token = await AsyncStorage.getItem('token'); | |
if (token) { | |
config.headers.Authorization = `Bearer ${token}`; | |
} | |
return config; | |
}, | |
error => { | |
return Promise.reject(error); | |
}, | |
); | |
// Is the marker being refreshed? | |
let isRefreshing = false; | |
// Retry queue, each item will be a function to be executed | |
let requests = [] as Array<any>; | |
instance.interceptors.response.use( | |
response => { | |
return response; | |
}, | |
(error: AxiosError) => { | |
if ( | |
error.response?.data?.detail === | |
'Given token not valid for any token type' | |
) { | |
const config = error.config; | |
if (!isRefreshing) { | |
isRefreshing = true; | |
return refreshToken() | |
.then(access => { | |
setNewToken(access); | |
config.headers['Authorization'] = `Bearer ${access}`; | |
// access has been refreshed to retry requests from all queues | |
requests.forEach(cb => cb(access)); | |
requests = []; | |
return instance(config); | |
}) | |
.catch(error => { | |
logOutUserLocal(store.dispatch); | |
}) | |
.finally(() => { | |
isRefreshing = false; | |
}); | |
} else { | |
// token is being refreshed and a promise that resolve has not been executed is returned | |
return new Promise(resolve => { | |
// Put resolve in the queue, save it in a function form, and execute it directly after token refreshes | |
requests.push((token: string) => { | |
config.headers['Authorization'] = `Bearer ${token}`; | |
resolve(instance(config)); | |
}); | |
}); | |
} | |
} | |
return Promise.reject(error); | |
}, | |
); | |
export default instance; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment