mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-11-03 19:07:00 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			111 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			111 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
export default function ({ $axios, store, $root, app }) {
 | 
						|
  // Track if we're currently refreshing to prevent multiple refresh attempts
 | 
						|
  let isRefreshing = false
 | 
						|
  let failedQueue = []
 | 
						|
 | 
						|
  const processQueue = (error, token = null) => {
 | 
						|
    failedQueue.forEach(({ resolve, reject }) => {
 | 
						|
      if (error) {
 | 
						|
        reject(error)
 | 
						|
      } else {
 | 
						|
        resolve(token)
 | 
						|
      }
 | 
						|
    })
 | 
						|
    failedQueue = []
 | 
						|
  }
 | 
						|
 | 
						|
  $axios.onRequest((config) => {
 | 
						|
    if (!config.url) {
 | 
						|
      console.error('Axios request invalid config', config)
 | 
						|
      return
 | 
						|
    }
 | 
						|
    if (config.url.startsWith('http:') || config.url.startsWith('https:')) {
 | 
						|
      return
 | 
						|
    }
 | 
						|
    const bearerToken = store.getters['user/getToken']
 | 
						|
    if (bearerToken) {
 | 
						|
      config.headers.common['Authorization'] = `Bearer ${bearerToken}`
 | 
						|
    }
 | 
						|
 | 
						|
    if (process.env.NODE_ENV === 'development') {
 | 
						|
      console.log('Making request to ' + config.url)
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  $axios.onError(async (error) => {
 | 
						|
    const originalRequest = error.config
 | 
						|
    const code = parseInt(error.response && error.response.status)
 | 
						|
    const message = error.response ? error.response.data || 'Unknown Error' : 'Unknown Error'
 | 
						|
 | 
						|
    console.error('Axios error', code, message)
 | 
						|
 | 
						|
    // Handle 401 Unauthorized (token expired)
 | 
						|
    if (code === 401 && !originalRequest._retry) {
 | 
						|
      // Skip refresh for auth endpoints to prevent infinite loops
 | 
						|
      if (originalRequest.url === '/auth/refresh' || originalRequest.url === '/login') {
 | 
						|
        // Refresh failed or login failed, redirect to login
 | 
						|
        store.commit('user/setUser', null)
 | 
						|
        store.commit('user/setAccessToken', null)
 | 
						|
        app.router.push('/login')
 | 
						|
        return Promise.reject(error)
 | 
						|
      }
 | 
						|
 | 
						|
      if (isRefreshing) {
 | 
						|
        // If already refreshing, queue this request
 | 
						|
        return new Promise((resolve, reject) => {
 | 
						|
          failedQueue.push({ resolve, reject })
 | 
						|
        })
 | 
						|
          .then((token) => {
 | 
						|
            if (!originalRequest.headers) {
 | 
						|
              originalRequest.headers = {}
 | 
						|
            }
 | 
						|
            originalRequest.headers['Authorization'] = `Bearer ${token}`
 | 
						|
            return $axios(originalRequest)
 | 
						|
          })
 | 
						|
          .catch((err) => {
 | 
						|
            return Promise.reject(err)
 | 
						|
          })
 | 
						|
      }
 | 
						|
 | 
						|
      originalRequest._retry = true
 | 
						|
      isRefreshing = true
 | 
						|
 | 
						|
      try {
 | 
						|
        // Attempt to refresh the token
 | 
						|
        // Updates store if successful, otherwise clears store and throw error
 | 
						|
        const newAccessToken = await store.dispatch('user/refreshToken')
 | 
						|
        if (!newAccessToken) {
 | 
						|
          console.error('No new access token received')
 | 
						|
          return Promise.reject(error)
 | 
						|
        }
 | 
						|
 | 
						|
        // Update the original request with new token
 | 
						|
        if (!originalRequest.headers) {
 | 
						|
          originalRequest.headers = {}
 | 
						|
        }
 | 
						|
        originalRequest.headers['Authorization'] = `Bearer ${newAccessToken}`
 | 
						|
 | 
						|
        // Process any queued requests
 | 
						|
        processQueue(null, newAccessToken)
 | 
						|
 | 
						|
        // Retry the original request
 | 
						|
        return $axios(originalRequest)
 | 
						|
      } catch (refreshError) {
 | 
						|
        console.error('Token refresh failed:', refreshError)
 | 
						|
 | 
						|
        // Process queued requests with error
 | 
						|
        processQueue(refreshError, null)
 | 
						|
 | 
						|
        // Redirect to login
 | 
						|
        app.router.push('/login')
 | 
						|
 | 
						|
        return Promise.reject(refreshError)
 | 
						|
      } finally {
 | 
						|
        isRefreshing = false
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    return Promise.reject(error)
 | 
						|
  })
 | 
						|
}
 |