Files
Furion/clients/axios_vue_react/axios-utils.js
2024-05-21 16:55:39 +08:00

256 lines
6.3 KiB
C#
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.
/**
* 当前版本v1.4.0
* 使用描述https://editor.swagger.io 代码生成 typescript-axios 辅组工具库
* 依赖说明:适配 axios 版本v0.21.4
* 视频教程https://www.bilibili.com/video/BV1EW4y1C71D
*/
import globalAxios from "axios";
import { Configuration } from "./api-services";
import { BASE_PATH } from "./api-services/base";
// 如果是 Angular 项目,则取消下面注释即可
// import { environment } from './environments/environment';
/**
* 接口服务器配置
*/
export const serveConfig = new Configuration({
// 如果是 Angular 项目,则取消下面注释,并删除 process.env.NODE_ENV !== "production"
// basePath: !environment.production
basePath:
process.env.NODE_ENV !== "production"
? "https://localhost:44342" // 开发环境服务器接口地址
: "https://furion.net", // 生产环境服务器接口地址
});
// token 键定义
export const accessTokenKey = "access-token";
export const refreshAccessTokenKey = `x-${accessTokenKey}`;
// 清除 token
export const clearAccessTokens = () => {
window.localStorage.removeItem(accessTokenKey);
window.localStorage.removeItem(refreshAccessTokenKey);
// 这里可以添加清除更多 Key =========================================
};
// 错误处理
export const throwError = (message) => {
throw new Error(message);
};
/**
* axios 默认实例
*/
export const axiosInstance = globalAxios;
// 这里可以配置 axios 更多选项 =========================================
axiosInstance.defaults.timeout = 1000 * 60 * 10; // 设置超时,默认 10 分钟
// axios 请求拦截
axiosInstance.interceptors.request.use(
(conf) => {
// 获取本地的 token
const accessToken = window.localStorage.getItem(accessTokenKey);
if (accessToken) {
// 将 token 添加到请求报文头中
conf.headers["Authorization"] = `Bearer ${accessToken}`;
// 判断 accessToken 是否过期
const jwt = decryptJWT(accessToken);
const exp = getJWTDate(jwt.exp);
// token 已经过期
if (new Date() >= exp) {
// 获取刷新 token
const refreshAccessToken = window.localStorage.getItem(
refreshAccessTokenKey
);
// 携带刷新 token
if (refreshAccessToken) {
conf.headers["X-Authorization"] = `Bearer ${refreshAccessToken}`;
}
}
}
// 这里编写请求拦截代码 =========================================
return conf;
},
(error) => {
// 处理请求错误
if (error.request) {
}
// 这里编写请求错误代码
return Promise.reject(error);
}
);
// axios 响应拦截
axiosInstance.interceptors.response.use(
(res) => {
// 检查并存储授权信息
checkAndStoreAuthentication(res);
// 处理规范化结果错误
const serve = res.data;
if (serve && serve.hasOwnProperty("errors") && serve.errors) {
// 处理规范化 401 授权问题
if (serve.errors === "401 Unauthorized") {
clearAccessTokens();
}
throwError(
!serve.errors
? "Request Error."
: typeof serve.errors === "string"
? serve.errors
: JSON.stringify(serve.errors)
);
return res;
}
// 这里编写响应拦截代码 =========================================
return res;
},
(error) => {
// 处理响应错误
if (error.response) {
// 获取响应对象并解析状态码
const res = error.response;
const status = res.status;
// 检查并存储授权信息
checkAndStoreAuthentication(res);
// 检查 401 权限
if (status === 401) {
clearAccessTokens();
}
}
// 这里编写响应错误代码
return Promise.reject(error);
}
);
/**
* 检查并存储授权信息
* @param res 响应对象
*/
export function checkAndStoreAuthentication(res) {
// 读取响应报文头 token 信息
var accessToken = res.headers[accessTokenKey];
var refreshAccessToken = res.headers[refreshAccessTokenKey];
// 判断是否是无效 token
if (accessToken === "invalid_token") {
clearAccessTokens();
}
// 判断是否存在刷新 token如果存在则存储在本地
else if (
refreshAccessToken &&
accessToken &&
accessToken !== "invalid_token"
) {
window.localStorage.setItem(accessTokenKey, accessToken);
window.localStorage.setItem(refreshAccessTokenKey, refreshAccessToken);
}
}
/**
* 包装 Promise 并返回 [Error, any]
* @param promise Promise 方法
* @param errorExt 自定义错误信息(拓展)
* @returns [Error, any]
*/
export function feature(promise, errorExt) {
return (
promise.then <
[null, T] >
((data) => [null, data]).catch <
[U, undefined] >
((err) => {
if (errorExt) {
const parsedError = Object.assign({}, err, errorExt);
return [parsedError, undefined];
}
return [err, undefined];
})
);
}
/**
* 获取/创建服务 API 实例
* @param apiType BaseAPI 派生类型
* @param configuration 服务器配置对象
* @param basePath 服务器地址
* @param axiosObject axios 实例
* @returns 服务API 实例
*/
export function getAPI(
apiType,
configuration = serveConfig,
basePath = BASE_PATH,
axiosObject = axiosInstance
) {
return new apiType(configuration, basePath, axiosObject);
}
/**
* 解密 JWT token 的信息
* @param token jwt token 字符串
* @returns <any>object
*/
export function decryptJWT(token) {
token = token.replace(/_/g, "/").replace(/-/g, "+");
var json = decodeURIComponent(escape(window.atob(token.split(".")[1])));
return JSON.parse(json);
}
/**
* 将 JWT 时间戳转换成 Date
* @description 主要针对 `exp``iat``nbf`
* @param timestamp 时间戳
* @returns Date 对象
*/
export function getJWTDate(timestamp) {
return new Date(timestamp * 1000);
}
/**
* 解析 token 授权信息
* @returns 解密后的 token 对象
*/
export function getAccessInfo() {
const accessToken = window.localStorage.getItem(accessTokenKey);
if (!accessToken) {
return null;
}
try {
const accessInfo = decryptJWT(accessToken);
return accessInfo;
} catch {
return null;
}
}
/**
* 实现异步延迟
* @param delay 延迟时间(毫秒)
* @returns
*/
export function sleep(delay) {
return new Promise((resolve) => setTimeout(resolve, delay));
}