Appearance
@sud-web/http
管理后台统一 HTTP 请求库,基于 axios 封装,提供 CSRF Token 管理、401 自动刷新、统一错误处理等功能。
特性
- ✅ CSRF Token 自动管理 - 自动从响应头获取并存储 CSRF Token,请求时自动携带
- ✅ 401 自动刷新 - 支持 Token 过期自动刷新,并发请求队列管理
- ✅ 统一错误处理 - 内置错误处理逻辑,支持自定义错误处理
- ✅ TypeScript 支持 - 完整的 TypeScript 类型定义
- ✅ 灵活的 Hooks - 支持自定义请求/响应拦截器
安装
bash
npm install @sud-web/http axios
# 或
pnpm add @sud-web/http axios
# 或
yarn add @sud-web/http axios注意: axios 是 peer dependency,需要单独安装。
快速开始
基础用法
typescript
import { createAxios } from '@sud-web/http'
// 创建 axios 实例
const http = createAxios({
axiosConfig: {
baseURL: 'https://api.example.com',
timeout: 10000
}
})
// 使用
const response = await http.get('/api/users')带错误提示的用法
typescript
import { createAxios } from '@sud-web/http'
import { ElMessage } from 'element-plus'
const http = createAxios({
axiosConfig: {
baseURL: 'https://api.example.com'
},
hooks: {
// 自定义错误提示
showErrorMessage: (msg) => {
ElMessage.error(msg)
}
}
})带 401 自动刷新的用法
typescript
import { createAxios, RefreshManager } from '@sud-web/http'
// 创建刷新管理器
const refreshManager = new RefreshManager(
async () => {
// 刷新 token 的逻辑(使用 cookie,后端自动处理)
const response = await axios.post('/api/refresh')
return response
},
{
// 刷新失败的回调
onRefreshFail: () => {
// 跳转到登录页
window.location.href = '/login'
}
}
)
// 创建 axios 实例
const http = createAxios({
axiosConfig: {
baseURL: 'https://api.example.com'
},
refreshManager
})API 文档
createAxios(options)
创建配置好的 axios 实例。
参数
typescript
interface CreateAxiosOptions {
hooks?: AxiosHooks // 自定义 hooks
refreshManager?: RefreshHandler // 401 刷新管理器
axiosConfig?: Record<string, any> // axios 配置
}AxiosHooks
typescript
interface AxiosHooks {
// 显示错误消息
showErrorMessage?: (msg: string) => void
// 请求拦截器
onRequest?: (
config: InternalAxiosRequestConfig
) => InternalAxiosRequestConfig | Promise<InternalAxiosRequestConfig>
// 响应拦截器(成功)
onResponse?: (
response: AxiosResponse
) => any | Promise<any>
// 响应拦截器(错误)
onResponseError?: (
error: AxiosError
) => any
}RefreshManager
401 自动刷新管理器。
构造函数
typescript
new RefreshManager(
refreshFn: () => Promise<any>,
options?: RefreshManagerOptions
)参数
refreshFn: 刷新 token 的函数,返回 Promiseoptions: 可选配置typescriptinterface RefreshManagerOptions { onRefreshFail?: () => void // 刷新失败时的回调 }
特性
- 并发请求队列: 多个请求同时 401 时,只会触发一次刷新,其他请求会加入队列等待
- 防重复刷新: 同一个请求不会重复触发刷新
- 自动重试: 刷新成功后自动重试原始请求
使用示例
示例 1: 基础配置
typescript
import { createAxios } from '@sud-web/http'
const http = createAxios({
axiosConfig: {
baseURL: 'https://api.example.com',
timeout: 10000,
headers: {
'Content-Type': 'application/json'
}
}
})
// 发送请求
const data = await http.get('/api/users')示例 2: 自定义请求拦截器
typescript
import { createAxios } from '@sud-web/http'
const http = createAxios({
axiosConfig: {
baseURL: 'https://api.example.com'
},
hooks: {
onRequest: async (config) => {
// 添加时间戳(token 通过 cookie 自动携带,无需手动添加)
config.params = {
...config.params,
_t: Date.now()
}
return config
}
}
})示例 3: 自定义响应处理
typescript
import { createAxios } from '@sud-web/http'
const http = createAxios({
hooks: {
// 自定义响应处理
onResponse: (response) => {
// 直接返回 response,不走默认的 code 判断
return response.data
},
// 自定义错误处理
onResponseError: (error) => {
if (error.response?.status === 403) {
// 处理 403 错误
console.error('没有权限')
}
return Promise.reject(error)
}
}
})完整的认证流程
typescript
import { createAxios, RefreshManager } from '@sud-web/http'
import { ElMessage } from 'element-plus'
// 刷新管理器
const refreshManager = new RefreshManager(
async () => {
// 刷新 token(使用 cookie,后端自动处理,无需手动传递和存储)
const response = await axios.post('/api/auth/refresh')
return response
},
{
onRefreshFail: () => {
// 跳转登录
window.location.href = '/login'
}
}
)
// 创建 http 实例
const http = createAxios({
axiosConfig: {
baseURL: import.meta.env.VITE_APP_BASE_URL,
timeout: 10000
},
hooks: {
showErrorMessage: (msg) => {
ElMessage.error(msg)
}
// token 通过 cookie 自动携带,无需在 onRequest 中手动添加
},
refreshManager
})
export default http完整示例(可直接使用)
这是一个完整的、可直接复制到项目中使用的示例:
typescript
import type { AxiosInstance, AxiosRequestConfig } from "axios"
import { createAxios, RefreshManager } from "@sud-web/http"
import { get } from "lodash-es"
import { refreshTokenApi } from "@/api/login"
import { redirectToLogin } from "@sud-web/utils"
import { ElMessage } from "element-plus" // 或使用其他 UI 库
const refreshManager = new RefreshManager(refreshTokenApi, {
onRefreshFail: () => {
console.log("[ refreshfail ] >")
redirectToLogin()
}
})
function createService() {
return createAxios({
refreshManager,
axiosConfig: {
timeout: 30000,
},
hooks: {
// 走默认处理才会执行, 成功响应自定义 code 错误提示
showErrorMessage(msg) {
ElMessage.error(msg || "接口错误")
},
onResponseError(error) {
console.log("[ error ] >", error)
const status = get(error, "response.status")
switch (status) {
case 400:
error.message = "请求错误"
break
case 403:
error.message = "拒绝访问"
break
case 404:
error.message = "请求地址出错"
break
case 408:
error.message = "请求超时"
break
case 500:
error.message = "服务器内部错误"
break
case 501:
error.message = "服务未实现"
break
case 502:
error.message = "网关错误"
break
case 503:
error.message = "服务不可用"
break
case 504:
error.message = "网关超时"
break
case 505:
error.message = "HTTP 版本不受支持"
break
default:
break
}
ElMessage({ message: error.message, type: "error" })
return Promise.reject(error)
}
}
})
}
/** 创建请求方法 */
function createRequestFunction(service: AxiosInstance) {
return function <T>(config: AxiosRequestConfig): Promise<T> {
return service(config)
}
}
/** 用于网络请求的实例 */
export const service = createService()
/** 用于网络请求的方法 */
export const request = createRequestFunction(service)使用方式:
typescript
// 使用封装的 request 方法
import { request } from '@/utils/request'
interface User {
id: number
name: string
}
const users = await request<User[]>('/api/users')注意事项:
- 需要根据项目实际情况调整
refreshTokenApi、redirectToLogin等工具函数 ElMessage是 element-plus 的消息组件,如果使用其他 UI 库可相应替换(如 vant 的Toast、naive-ui 的useMessage等)- 如果使用 Vite,可以取消注释
baseURL配置
示例 6: 禁用特定接口的自动刷新
typescript
// 某些接口(如refresh接口)不需要自动刷新
const response = await http.post('/api/refresh', {}, {
config: {
enableRefresh: false // 禁用自动刷新
}
})默认行为
响应处理
- 成功响应 (
code === 0): 直接返回response.data - 业务错误 (
code !== 0):- 如果提供了
showErrorMessage,会调用它显示错误消息 - 返回
Promise.reject(response.data)
- 如果提供了
CSRF Token
- 自动从响应头
x-xsrf-token获取并存储到localStorage - 请求时自动在请求头
X-XSRF-TOKEN中携带
401 处理
- 如果提供了
refreshManager,遇到 401 时会自动调用刷新逻辑 - 刷新成功后自动重试原始请求
- 并发请求会被加入队列,等待刷新完成后统一处理
注意事项
- 认证方式: 推荐使用 Cookie 方式,后端自动处理 token 的存储和携带,前端无需手动管理。使用代理时,Cookie 会自动处理,无需额外配置
- CSRF Token 存储: CSRF Token 存储在
localStorage中,key 为x-xsrf-token,会自动从响应头获取并存储 - 响应格式: 默认期望响应格式为
{ code: number, data?: any, msg?: string } - 401 刷新: 只有提供了
refreshManager才会自动处理 401 - 并发请求: 多个请求同时 401 时,只会触发一次刷新,其他请求会等待
- TypeScript: 建议使用 TypeScript 以获得完整的类型提示