Files
member-platform/frontend/src/api/http.js

96 lines
2.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import axios from 'axios'
import router from '@/router'
const BASE_URL = import.meta.env.VITE_API_BASE_URL
let refreshPromise = null
async function refreshAccessToken() {
if (refreshPromise) return refreshPromise
const refreshToken = localStorage.getItem('refresh_token')
if (!refreshToken) throw new Error('missing_refresh_token')
refreshPromise = axios
.post(`${BASE_URL}/auth/refresh`, { refresh_token: refreshToken })
.then((res) => {
const nextAccessToken = res.data?.access_token
const nextRefreshToken = res.data?.refresh_token || refreshToken
if (!nextAccessToken) {
throw new Error('missing_access_token')
}
localStorage.setItem('access_token', nextAccessToken)
localStorage.setItem('refresh_token', nextRefreshToken)
return nextAccessToken
})
.finally(() => {
refreshPromise = null
})
return refreshPromise
}
function hardLogoutToLogin() {
localStorage.removeItem('access_token')
localStorage.removeItem('refresh_token')
router.push('/login')
}
// 使用者 API帶 Bearer token
export const userHttp = axios.create({ baseURL: BASE_URL })
userHttp.interceptors.request.use(config => {
const token = localStorage.getItem('access_token')
if (token) {
config.headers['Authorization'] = `Bearer ${token}`
}
return config
})
userHttp.interceptors.response.use(
res => res,
async err => {
const original = err.config || {}
if (err.response?.status === 401 && !original._retriedByRefresh) {
original._retriedByRefresh = true
try {
const nextToken = await refreshAccessToken()
original.headers = original.headers || {}
original.headers['Authorization'] = `Bearer ${nextToken}`
return userHttp.request(original)
} catch (_refreshErr) {
hardLogoutToLogin()
}
}
return Promise.reject(err)
}
)
// 管理員 API只帶 Bearer token後端再檢查 admin 群組)
export const adminHttp = axios.create({ baseURL: BASE_URL })
adminHttp.interceptors.request.use(config => {
const token = localStorage.getItem('access_token')
if (token) {
config.headers['Authorization'] = `Bearer ${token}`
}
return config
})
adminHttp.interceptors.response.use(
res => res,
async err => {
const original = err.config || {}
if (err.response?.status === 401 && !original._retriedByRefresh) {
original._retriedByRefresh = true
try {
const nextToken = await refreshAccessToken()
original.headers = original.headers || {}
original.headers['Authorization'] = `Bearer ${nextToken}`
return adminHttp.request(original)
} catch (_refreshErr) {
hardLogoutToLogin()
}
}
return Promise.reject(err)
}
)