Files
AIGC/demo/frontend/src/api/request.js

180 lines
6.4 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 { ElMessage } from 'element-plus'
import router from '@/router'
import { getApiBaseURL } from '@/utils/apiHelper'
// 创建axios实例
// 自动检测:如果通过 Nginx 访问(包含 ngrok使用相对路径否则使用完整 URL
const api = axios.create({
baseURL: getApiBaseURL(),
timeout: 900000, // 增加到15分钟适应视频生成时间
withCredentials: true,
maxRedirects: 0, // 不自动跟随重定向手动处理302
headers: {
'Content-Type': 'application/json'
},
validateStatus: function (status) {
// 允许所有状态码包括302让拦截器处理
return status >= 200 && status < 600
}
})
// 请求拦截器
api.interceptors.request.use(
(config) => {
// 登录相关的接口不需要添加token
const loginUrls = [
'/auth/login',
'/auth/login/email',
'/auth/register',
'/verification/email/send',
'/verification/email/verify',
'/verification/email/dev-set',
'/public/'
]
// 检查当前请求是否是登录相关接口
const isLoginRequest = loginUrls.some(url => config.url.includes(url))
if (!isLoginRequest) {
// 非登录请求才添加Authorization头
const token = localStorage.getItem('token')
if (token && token !== 'null' && token.trim() !== '') {
config.headers.Authorization = `Bearer ${token}`
console.log('请求拦截器添加Authorization头token长度:', token.length)
} else {
console.warn('请求拦截器未找到有效的token')
}
} else {
console.log('请求拦截器登录相关请求不添加token:', config.url)
}
return config
},
(error) => {
console.error('请求拦截器错误:', error)
return Promise.reject(error)
}
)
// 响应拦截器
api.interceptors.response.use(
(response) => {
// 检查是否是HTML响应可能是302重定向的结果
if (response.data && typeof response.data === 'string' && response.data.trim().startsWith('<!DOCTYPE')) {
console.error('收到HTML响应可能是认证失败:', response.config.url)
// 只有非登录请求才清除token并跳转
const loginUrls = ['/auth/login', '/auth/login/email', '/auth/register', '/verification/', '/public/']
const isLoginRequest = loginUrls.some(url => response.config.url.includes(url))
if (!isLoginRequest) {
// 清除无效的token并跳转到登录页
localStorage.removeItem('token')
localStorage.removeItem('user')
// 避免重复跳转
if (router.currentRoute.value.path !== '/login') {
ElMessage.error('认证失败,请重新登录')
router.push('/login')
}
}
// 返回错误,让调用方知道这是认证失败
return Promise.reject(new Error('认证失败收到HTML响应'))
}
// 检查302重定向
if (response.status === 302) {
console.error('收到302重定向可能是认证失败:', response.config.url)
// 只有非登录请求才清除token并跳转
const loginUrls = ['/auth/login', '/auth/login/email', '/auth/register', '/verification/', '/public/']
const isLoginRequest = loginUrls.some(url => response.config.url.includes(url))
if (!isLoginRequest) {
localStorage.removeItem('token')
localStorage.removeItem('user')
if (router.currentRoute.value.path !== '/login') {
ElMessage.error('认证失败,请重新登录')
router.push('/login')
}
}
return Promise.reject(new Error('认证失败302重定向'))
}
// 直接返回response让调用方处理data
return response
},
(error) => {
if (error.response) {
const { status, data } = error.response
// 检查响应数据是否是HTML302重定向的结果
if (data && typeof data === 'string' && data.trim().startsWith('<!DOCTYPE')) {
console.error('收到HTML响应可能是302重定向:', error.config.url)
// 只有非登录请求才清除token并跳转
const loginUrls = ['/auth/login', '/auth/login/email', '/auth/register', '/verification/', '/public/']
const isLoginRequest = loginUrls.some(url => error.config.url.includes(url))
if (!isLoginRequest) {
localStorage.removeItem('token')
localStorage.removeItem('user')
if (router.currentRoute.value.path !== '/login') {
ElMessage.error('认证失败,请重新登录')
router.push('/login')
}
}
return Promise.reject(error)
}
switch (status) {
case 401:
case 302:
// 只有非登录请求才清除token并跳转
const loginUrls = ['/auth/login', '/auth/login/email', '/auth/register', '/verification/', '/public/']
const isLoginRequest = loginUrls.some(url => error.config.url.includes(url))
if (!isLoginRequest) {
// 302也可能是认证失败导致的
localStorage.removeItem('token')
localStorage.removeItem('user')
if (router.currentRoute.value.path !== '/login') {
ElMessage.error('认证失败,请重新登录')
router.push('/login')
}
}
break
case 403:
// 403可能是权限不足或CORS问题
// 如果是登录请求的403不要显示"权限不足",而是显示具体错误信息
const loginUrls403 = ['/auth/login', '/auth/login/email', '/auth/register', '/verification/', '/public/']
const isLoginRequest403 = loginUrls403.some(url => error.config.url.includes(url))
if (!isLoginRequest403) {
ElMessage.error('权限不足')
} else {
// 登录请求的403显示具体错误或网络问题
ElMessage.error(data?.message || '请求失败,请检查网络连接')
}
break
case 404:
ElMessage.error('请求的资源不存在')
break
case 500:
ElMessage.error('服务器内部错误')
break
default:
ElMessage.error(data?.message || '请求失败')
}
} else if (error.request) {
ElMessage.error('网络错误,请检查网络连接')
} else {
ElMessage.error('请求配置错误')
}
return Promise.reject(error)
}
)
export default api