fix(node-player): auto-refresh expired JWT tokens on 401
Adds an axios response interceptor that catches 401 errors, fetches a fresh access token from /auth/token, and retries the original request. Concurrent refresh attempts are deduplicated. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,38 @@ export function clearAuthToken() {
|
||||
delete furumiApi.defaults.headers.common['Authorization']
|
||||
}
|
||||
|
||||
async function refreshToken(): Promise<boolean> {
|
||||
try {
|
||||
const res = await fetch('/auth/token', { credentials: 'include' })
|
||||
if (!res.ok) return false
|
||||
const data = await res.json()
|
||||
if (data.access_token) {
|
||||
setAuthToken(data.access_token)
|
||||
return true
|
||||
}
|
||||
} catch { /* ignore */ }
|
||||
return false
|
||||
}
|
||||
|
||||
let refreshPromise: Promise<boolean> | null = null
|
||||
|
||||
furumiApi.interceptors.response.use(
|
||||
(response) => response,
|
||||
async (error) => {
|
||||
const original = error.config
|
||||
if (error.response?.status === 401 && !original._retried) {
|
||||
original._retried = true
|
||||
// Deduplicate concurrent refresh attempts
|
||||
if (!refreshPromise) {
|
||||
refreshPromise = refreshToken().finally(() => { refreshPromise = null })
|
||||
}
|
||||
const ok = await refreshPromise
|
||||
if (ok) return furumiApi(original)
|
||||
}
|
||||
return Promise.reject(error)
|
||||
},
|
||||
)
|
||||
|
||||
export async function getArtists(): Promise<Artist[] | null> {
|
||||
const res = await furumiApi.get<Artist[]>('/artists').catch(() => null)
|
||||
return res?.data ?? null
|
||||
|
||||
Reference in New Issue
Block a user