mirror of
https://github.com/truewhile/MeBox.git
synced 2026-09-29 03:26:37 +08:00
fix: harden bot accounts and download handling
This commit is contained in:
+32
-8
@@ -12,19 +12,31 @@ export const api = axios.create({
|
||||
|
||||
// Flag to prevent multiple simultaneous refresh attempts
|
||||
let isRefreshing = false
|
||||
let refreshSubscribers: Array<(token: string) => void> = []
|
||||
let refreshSubscribers: Array<{
|
||||
resolve: (token: string) => void
|
||||
reject: (error: unknown) => void
|
||||
}> = []
|
||||
|
||||
// Subscribe to token refresh
|
||||
function subscribeTokenRefresh(callback: (token: string) => void) {
|
||||
refreshSubscribers.push(callback)
|
||||
function subscribeTokenRefresh(resolve: (token: string) => void, reject: (error: unknown) => void) {
|
||||
refreshSubscribers.push({ resolve, reject })
|
||||
}
|
||||
|
||||
// Notify all subscribers about new token
|
||||
function onTokenRefreshed(newToken: string) {
|
||||
refreshSubscribers.forEach(callback => callback(newToken))
|
||||
refreshSubscribers.forEach((subscriber) => subscriber.resolve(newToken))
|
||||
refreshSubscribers = []
|
||||
}
|
||||
|
||||
function onTokenRefreshFailed(error: unknown) {
|
||||
refreshSubscribers.forEach((subscriber) => subscriber.reject(error))
|
||||
refreshSubscribers = []
|
||||
}
|
||||
|
||||
function isRefreshRequest(config?: InternalAxiosRequestConfig | null): boolean {
|
||||
return Boolean(config?.url?.includes('/auth/refresh'))
|
||||
}
|
||||
|
||||
// Add auth token to requests
|
||||
api.interceptors.request.use((config) => {
|
||||
const token = useAuthStore.getState().token
|
||||
@@ -51,16 +63,21 @@ api.interceptors.response.use(
|
||||
const originalRequest = err.config as InternalAxiosRequestConfig & { _retry?: boolean }
|
||||
|
||||
// If 401 and not already retried
|
||||
if (err.response?.status === 401 && originalRequest && !originalRequest._retry) {
|
||||
if (
|
||||
err.response?.status === 401 &&
|
||||
originalRequest &&
|
||||
!originalRequest._retry &&
|
||||
!isRefreshRequest(originalRequest)
|
||||
) {
|
||||
if (isRefreshing) {
|
||||
// Wait for token refresh to complete
|
||||
return new Promise((resolve) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
subscribeTokenRefresh((token: string) => {
|
||||
if (originalRequest.headers) {
|
||||
originalRequest.headers.Authorization = `Bearer ${token}`
|
||||
}
|
||||
resolve(api(originalRequest))
|
||||
})
|
||||
}, reject)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -80,10 +97,17 @@ api.interceptors.response.use(
|
||||
}
|
||||
} catch (refreshError) {
|
||||
isRefreshing = false
|
||||
refreshSubscribers = []
|
||||
onTokenRefreshFailed(refreshError)
|
||||
useAuthStore.getState().logout()
|
||||
if (typeof window !== 'undefined' && window.location.pathname !== '/login') {
|
||||
window.location.href = '/login'
|
||||
}
|
||||
return Promise.reject(refreshError)
|
||||
}
|
||||
|
||||
// Refresh failed, logout
|
||||
isRefreshing = false
|
||||
onTokenRefreshFailed(err)
|
||||
useAuthStore.getState().logout()
|
||||
if (typeof window !== 'undefined' && window.location.pathname !== '/login') {
|
||||
window.location.href = '/login'
|
||||
|
||||
Reference in New Issue
Block a user