Projekt

Obecné

Profil

Stáhnout (2.96 KB) Statistiky
| Větev: | Tag: | Revize:
1
import axios from 'axios'
2
import { Store } from 'redux'
3
import conf from '../config/conf'
4
import config from '../config/conf'
5
import { AppStore } from '../features/redux/store'
6

    
7
let store: AppStore // this will get injected in index.tsx
8

    
9
export const injectStore = (_store: Store) => {
10
    store = _store
11
}
12

    
13
// Error
14
export interface ApiError {}
15

    
16
const createBaseInstance = () =>
17
    axios.create({
18
        baseURL: config.baseUrl,
19
        headers: {}
20
    })
21

    
22
const axiosInstance = createBaseInstance()
23

    
24
axiosInstance.interceptors.request.use(
25
    (config) => {
26
        const accessToken = store.getState().user.accessToken // get the access token from the store
27
        if (accessToken) {
28
            // @ts-ignore (axios typescript types are a crime and this will always be defined)
29
            config.headers['Authorization'] = accessToken as string
30
        }
31

    
32
        return config
33
    },
34
    (err) => {
35
        Promise.reject(err)
36
    }
37
)
38

    
39
axiosInstance.interceptors.response.use(
40
    (res) => res,
41
    async (err) => {
42
        const originalConfig = err.config
43

    
44

    
45
        // Original URL might be login in which case we don't want to refresh the access token
46
        // Since the user just failed to log in and no token expired
47
        if (originalConfig.url === '/login' || !err.response) {
48
            return Promise.reject(err)
49
        }
50

    
51
        // If the error is not a 401 reject this
52
        if (err.response.status !== 401) {
53
            return Promise.reject(err)
54
        }
55

    
56
        // We need to set the refresh token in the auth header
57
        const oldRefreshToken = store.getState().user.refreshToken
58

    
59
        // If there is no refresh token we simply log the user out
60
        if (!oldRefreshToken) {
61
            store.dispatch({ type: 'user/logout' })
62
        }
63

    
64
        // Try refreshing the JWT
65
        try {
66
            // For some reason axios refuses to create instance here so just use fetch
67
            // Send the request
68
            const res = await fetch(`${conf.baseUrl}/users/token`, {
69
                method: 'GET',
70
                // credentials: 'include',
71
                headers: {
72
                    'Authorization': oldRefreshToken as string
73
                }
74
            })
75

    
76
            const json = await res.json()
77
            const [ accessToken, refreshToken ] = [json.access_token, json.refresh_token]
78

    
79
            // Set the new tokens
80
            store.dispatch({
81
                type: 'user/refreshTokens',
82
                payload: { accessToken, refreshToken },
83
            })
84

    
85
            // Set this to retry the request that failed
86
            originalConfig.retry = true
87

    
88
            // Return the failed instance so it can retry
89
            return axiosInstance(originalConfig)
90
        } catch (err: any) {
91
            // If the refresh token fails we log the user out
92
            store.dispatch({ type: 'user/logout' })
93
            originalConfig.retry = false // do not retry we are logged out
94
            return originalConfig
95
        }
96
    }
97
)
98

    
99
export default axiosInstance
    (1-1/1)