64 lines
1.9 KiB
TypeScript
64 lines
1.9 KiB
TypeScript
import axios from 'axios'
|
|
import { clearTokens, getToken } from './auth'
|
|
|
|
type UnifiedResult<T> = {
|
|
code?: number
|
|
type?: string
|
|
message?: string
|
|
result?: T
|
|
errors?: unknown
|
|
}
|
|
|
|
let redirectingToLogin = false
|
|
|
|
function handleUnauthorized(requestAuthorization?: unknown) {
|
|
// A response from the previous session must not clear a newly signed-in session.
|
|
const currentToken = getToken()
|
|
if (currentToken && requestAuthorization !== `Bearer ${currentToken}`) return
|
|
clearTokens()
|
|
if (typeof window !== 'undefined' && window.location.pathname !== '/auth' && !redirectingToLogin) {
|
|
redirectingToLogin = true
|
|
window.location.replace('/auth')
|
|
}
|
|
}
|
|
|
|
const http = axios.create({
|
|
baseURL: '/',
|
|
timeout: 15000
|
|
})
|
|
|
|
http.interceptors.request.use((config) => {
|
|
const token = getToken()
|
|
if (token) config.headers.Authorization = `Bearer ${token}`
|
|
return config
|
|
})
|
|
|
|
http.interceptors.response.use(
|
|
((response: any) => {
|
|
const body = response.data as UnifiedResult<unknown>
|
|
if (body && typeof body === 'object') {
|
|
if (body.code === 401) {
|
|
handleUnauthorized(response.config?.headers?.Authorization)
|
|
return Promise.reject(new Error(body.message || '登录已过期,请重新登录'))
|
|
}
|
|
}
|
|
if (body && typeof body === 'object' && 'result' in body) {
|
|
if (body.type && body.type !== 'success') {
|
|
return Promise.reject(new Error(body.message || '请求失败'))
|
|
}
|
|
return body.result
|
|
}
|
|
return body
|
|
}) as any,
|
|
(error) => {
|
|
if (error.response?.status === 401) {
|
|
handleUnauthorized(error.config?.headers?.Authorization ?? error.response?.config?.headers?.Authorization)
|
|
}
|
|
const body = error.response?.data as UnifiedResult<unknown> | undefined
|
|
const message = body?.message || error.message || '网络请求失败'
|
|
return Promise.reject(new Error(message))
|
|
}
|
|
)
|
|
|
|
export default http
|