fix: TypeError: Cannot read properties of undefined (reading '__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED') at react-dom-CErclyH-.js:1:5784
This commit is contained in:
@@ -1,20 +1,5 @@
|
||||
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios'
|
||||
import { message } from 'antd'
|
||||
import {
|
||||
aesDecrypt,
|
||||
aesEncrypt,
|
||||
get16RandomNum,
|
||||
getRsaKeys,
|
||||
rsaDecrypt,
|
||||
rsaEncrypt,
|
||||
} from '@/utils/encrypt/encrypt.ts'
|
||||
import { handleLocalforage } from '@/utils/localforage'
|
||||
|
||||
let frontPrivateKey: any
|
||||
let afterPublicKey: any
|
||||
async function getAfterPublicKey() {
|
||||
afterPublicKey = await handleLocalforage.getItem('afterPublicKey')
|
||||
}
|
||||
class Request {
|
||||
private instance: AxiosInstance | undefined
|
||||
|
||||
@@ -23,43 +8,6 @@ class Request {
|
||||
// 全局请求拦截
|
||||
this.instance.interceptors.request.use(
|
||||
(config) => {
|
||||
if (config.headers['isEncrypt']) {
|
||||
if (config.method === 'post' || config.method === 'put') {
|
||||
let privateKey: any
|
||||
let publicKey: any
|
||||
getRsaKeys().then((res: any) => {
|
||||
privateKey = res.privateKey
|
||||
publicKey = res.publicKey
|
||||
})
|
||||
getAfterPublicKey()
|
||||
frontPrivateKey = privateKey
|
||||
|
||||
//每次请求生成aeskey
|
||||
const aesKey = get16RandomNum()
|
||||
if (afterPublicKey) {
|
||||
//用登陆后后端生成并返回给前端的的RSA密钥对的公钥将AES16位密钥进行加密
|
||||
const aesKeyByRsa = rsaEncrypt(aesKey, afterPublicKey)
|
||||
|
||||
//使用AES16位的密钥将请求报文加密(使用的是加密前的aes密钥)
|
||||
if (config.data) {
|
||||
const data = aesEncrypt(aesKey, JSON.stringify(config.data))
|
||||
config.data = {
|
||||
data: data,
|
||||
aeskey: aesKeyByRsa,
|
||||
frontPublicKey: publicKey,
|
||||
}
|
||||
}
|
||||
if (config.params) {
|
||||
const data = aesEncrypt(aesKey, JSON.stringify(config.params))
|
||||
config.params = {
|
||||
params: data,
|
||||
aeskey: aesKeyByRsa,
|
||||
frontPublicKey: publicKey,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return config
|
||||
},
|
||||
(error) => {
|
||||
@@ -71,20 +19,9 @@ class Request {
|
||||
this.instance.interceptors.response.use(
|
||||
(res) => {
|
||||
if (res.data.code && res.data.code !== 200) {
|
||||
message.error(res.data.message)
|
||||
message.error(res.data.message).then()
|
||||
return Promise.reject(res.data)
|
||||
}
|
||||
//后端返回的通过rsa加密后的aes密钥
|
||||
const aesKeyByRsa: any = res.data.aesKeyByRsa
|
||||
if (aesKeyByRsa) {
|
||||
localStorage.setItem('afterPublicKey', aesKeyByRsa)
|
||||
//通过rsa的私钥对后端返回的加密的aeskey进行解密
|
||||
const aesKey: any = rsaDecrypt(aesKeyByRsa, frontPrivateKey)
|
||||
//使用解密后的aeskey对加密的返回报文进行解密
|
||||
res.data = JSON.parse(JSON.parse(aesDecrypt(aesKey, res.data)))
|
||||
|
||||
return res.data
|
||||
}
|
||||
return res.data
|
||||
},
|
||||
(error) => {
|
||||
@@ -180,5 +117,29 @@ class Request {
|
||||
})
|
||||
})
|
||||
}
|
||||
put(url: string, data = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.instance
|
||||
?.put(url, data)
|
||||
.then((res) => {
|
||||
resolve(res)
|
||||
})
|
||||
.catch((err) => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
delete(url: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.instance
|
||||
?.delete(url)
|
||||
.then((res) => {
|
||||
resolve(res)
|
||||
})
|
||||
.catch((err) => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
export default Request
|
||||
|
@@ -1,233 +0,0 @@
|
||||
import axios, {
|
||||
AxiosError,
|
||||
AxiosInstance,
|
||||
AxiosRequestConfig,
|
||||
AxiosResponse,
|
||||
InternalAxiosRequestConfig,
|
||||
} from 'axios'
|
||||
import { message } from 'antd'
|
||||
import router from '@/router'
|
||||
// import { aesEncrypt, get16RandomNum, getRsaKeys, rsaEncrypt } from '@/utils/encrypt/encrypt.ts'
|
||||
// 数据返回的接口
|
||||
// 定义请求响应参数,不含data
|
||||
// interface Result {
|
||||
// code: number
|
||||
// msg: string
|
||||
// }
|
||||
|
||||
// 请求响应参数,包含data
|
||||
// interface ResultData<T = never> extends Result {
|
||||
// data?: T
|
||||
// }
|
||||
interface UploadFileItemModel {
|
||||
name: string
|
||||
value: string | Blob
|
||||
}
|
||||
type UploadRequestConfig = Omit<AxiosRequestConfig, 'url' | 'data'>
|
||||
|
||||
const URL = import.meta.env.VITE_API_BASE_URL
|
||||
enum RequestEnums {
|
||||
TIMEOUT = 20000,
|
||||
OVERDUE = 600, // 登录失效
|
||||
FAIL = 999, // 请求失败
|
||||
SUCCESS = 200, // 请求成功
|
||||
}
|
||||
const config = {
|
||||
// 默认地址
|
||||
baseURL: URL as string,
|
||||
// 设置超时时间
|
||||
timeout: RequestEnums.TIMEOUT as number,
|
||||
// 跨域时候允许携带凭证
|
||||
withCredentials: true,
|
||||
}
|
||||
// let frontPrivateKey :string = ''
|
||||
class RequestHttp {
|
||||
// 定义成员变量并指定类型
|
||||
service: AxiosInstance
|
||||
public constructor(config: AxiosRequestConfig) {
|
||||
// 实例化axios
|
||||
this.service = axios.create(config)
|
||||
/**
|
||||
* 请求拦截器
|
||||
* 客户端发送请求 -> [请求拦截器] -> 服务器
|
||||
*/
|
||||
this.service.interceptors.request.use(
|
||||
(config: InternalAxiosRequestConfig | any) => {
|
||||
if (localStorage.getItem('token')) {
|
||||
const token = localStorage.getItem('token') || ''
|
||||
return {
|
||||
...config,
|
||||
headers: {
|
||||
'x-access-token': token, // 请求头中携带token信息
|
||||
},
|
||||
}
|
||||
}
|
||||
// if (config.headers['isEncrypt']) {
|
||||
// config.headers['Content-Type'] = 'application/json;charset=utf-8'
|
||||
// if (config.method === 'post' || config.method === 'put') {
|
||||
// const { privateKey, publicKey } = await getRsaKeys()
|
||||
// const afterPublicKey = sessionStorage.getItem('afterPublicKey')
|
||||
// frontPrivateKey = privateKey
|
||||
// //每次请求生成aeskey
|
||||
// const aesKey = get16RandomNum()
|
||||
// //用登陆后后端生成并返回给前端的的RSA密钥对的公钥将AES16位密钥进行加密
|
||||
// const aesKeyByRsa = rsaEncrypt(aesKey, afterPublicKey)
|
||||
// //使用AES16位的密钥将请求报文加密(使用的是加密前的aes密钥)
|
||||
// if (config.data) {
|
||||
// const data = aesEncrypt(aesKey, JSON.stringify(config.data))
|
||||
// config.data = {
|
||||
// data: data,
|
||||
// aesKey: aesKeyByRsa,
|
||||
// frontPublicKey: publicKey,
|
||||
// }
|
||||
// }
|
||||
// if (config.params) {
|
||||
// const data = aesEncrypt(aesKey, JSON.stringify(config.params))
|
||||
// config.params = {
|
||||
// params: data,
|
||||
// aesKey: aesKeyByRsa,
|
||||
// frontPublicKey: publicKey,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
},
|
||||
(error: AxiosError) => {
|
||||
// 请求报错
|
||||
return Promise.reject(error)
|
||||
},
|
||||
)
|
||||
|
||||
/**
|
||||
* 响应拦截器
|
||||
* 服务器换返回信息 -> [拦截统一处理] -> 客户端JS获取到信息
|
||||
*/
|
||||
this.service.interceptors.response.use(
|
||||
(response: AxiosResponse) => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
const { data, config } = response // 解构
|
||||
if (data.code === RequestEnums.OVERDUE) {
|
||||
// 登录信息失效,应跳转到登录页面,并清空本地的token
|
||||
localStorage.setItem('token', '')
|
||||
return Promise.reject(data)
|
||||
}
|
||||
// 全局错误信息拦截(防止下载文件得时候返回数据流,没有code,直接报错)
|
||||
if (data.code && data.code !== RequestEnums.SUCCESS) {
|
||||
message.error(data) // 此处也可以使用组件提示报错信息
|
||||
return Promise.reject(data)
|
||||
}
|
||||
return data
|
||||
},
|
||||
(error: AxiosError) => {
|
||||
const { response } = error
|
||||
if (response) {
|
||||
this.handleCode(response.status)
|
||||
}
|
||||
if (!window.navigator.onLine) {
|
||||
message.error('网络连接失败')
|
||||
// 可以跳转到错误页面,也可以不做操作
|
||||
return router.push({
|
||||
path: '/404',
|
||||
})
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
handleCode(code: number): void {
|
||||
switch (code) {
|
||||
case 400:
|
||||
message.error('请求错误(400)')
|
||||
break
|
||||
case 401:
|
||||
message.error('未授权,请重新登录(401)')
|
||||
break
|
||||
case 403:
|
||||
message.error('拒绝访问(403)')
|
||||
break
|
||||
case 404:
|
||||
message.error('请求出错(404)')
|
||||
break
|
||||
case 408:
|
||||
message.error('请求超时(408)')
|
||||
break
|
||||
case 500:
|
||||
message.error('服务器错误(500)')
|
||||
break
|
||||
case 501:
|
||||
message.error('服务未实现(501)')
|
||||
break
|
||||
case 502:
|
||||
message.error('网络错误(502)')
|
||||
break
|
||||
case 503:
|
||||
message.error('服务不可用(503)')
|
||||
break
|
||||
case 504:
|
||||
message.error('网络超时(504)')
|
||||
break
|
||||
case 505:
|
||||
message.error('HTTP版本不受支持(505)')
|
||||
break
|
||||
default:
|
||||
message.error(`连接出错(${code})!`)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
request<T = any>(config: AxiosRequestConfig): Promise<T> {
|
||||
/**
|
||||
* TODO: execute other methods according to config
|
||||
*/
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
this.service
|
||||
.request<T>(config)
|
||||
.then((res: any) => {
|
||||
resolve(res)
|
||||
})
|
||||
.catch((err) => {
|
||||
reject(err)
|
||||
})
|
||||
} catch (err) {
|
||||
return Promise.reject(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
// 常用方法封装
|
||||
get<T = any>(config: AxiosRequestConfig): Promise<T> {
|
||||
return this.request({ method: 'GET', ...config })
|
||||
}
|
||||
post<T = any>(config: AxiosRequestConfig): Promise<T> {
|
||||
return this.request({ method: 'POST', ...config })
|
||||
}
|
||||
put<T = any>(config: AxiosRequestConfig): Promise<T> {
|
||||
return this.request({ method: 'PUT', ...config })
|
||||
}
|
||||
delete<T = any>(config: AxiosRequestConfig): Promise<T> {
|
||||
return this.request({ method: 'DELETE', ...config })
|
||||
}
|
||||
upload<T = string>(
|
||||
fileItem: UploadFileItemModel,
|
||||
config?: UploadRequestConfig,
|
||||
): Promise<T> | null {
|
||||
if (!import.meta.env.VITE_UPLOAD_URL) return null
|
||||
|
||||
const fd = new FormData()
|
||||
fd.append(fileItem.name, fileItem.value)
|
||||
let configCopy: UploadRequestConfig
|
||||
if (!config) {
|
||||
configCopy = {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
}
|
||||
} else {
|
||||
config.headers!['Content-Type'] = 'multipart/form-data'
|
||||
configCopy = config
|
||||
}
|
||||
return this.request({ url: import.meta.env.VITE_UPLOAD_URL, data: fd, ...configCopy })
|
||||
}
|
||||
}
|
||||
// 导出一个实例对象
|
||||
export default new RequestHttp(config)
|
@@ -1,13 +1,6 @@
|
||||
import HomeIndex from '@/components/HomeIndex'
|
||||
import { useEffect } from 'react'
|
||||
import { handleLocalforage } from '@/utils/localforage'
|
||||
|
||||
export default () => {
|
||||
useEffect(() => {
|
||||
handleLocalforage.getItem('token').then((res: any) => {
|
||||
console.log(JSON.parse(res))
|
||||
})
|
||||
}, [])
|
||||
return (
|
||||
<div>
|
||||
<HomeIndex />
|
||||
|
@@ -145,19 +145,19 @@ export default defineConfig(({ mode }) => {
|
||||
brotliSize: true, // 启用 brotli 压缩大小报告
|
||||
chunkSizeWarningLimit: 2000, // chunk 大小警告的限制
|
||||
watch: null, // 设置为 {} 则会启用 rollup 的监听器
|
||||
rollupOptions: {
|
||||
// 自定义底层的 Rollup 打包配置
|
||||
output: {
|
||||
chunkFileNames: 'js/[name]-[hash].js', // 引入文件名的名称
|
||||
entryFileNames: 'js/[name]-[hash].js', // 包的入口文件名称
|
||||
assetFileNames: '[ext]/[name]-[hash].[ext]', // 资源文件像 字体,图片等
|
||||
manualChunks(id) {
|
||||
if (id.includes('node_modules')) {
|
||||
return id.toString().split('node_modules/')[1].split('/')[0].toString()
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
// rollupOptions: {
|
||||
// // 自定义底层的 Rollup 打包配置
|
||||
// output: {
|
||||
// chunkFileNames: 'js/[name]-[hash].js', // 引入文件名的名称
|
||||
// entryFileNames: 'js/[name]-[hash].js', // 包的入口文件名称
|
||||
// assetFileNames: '[ext]/[name]-[hash].[ext]', // 资源文件像 字体,图片等
|
||||
// manualChunks(id) {
|
||||
// if (id.includes('node_modules')) {
|
||||
// return id.toString().split('node_modules/')[1].split('/')[0].toString()
|
||||
// }
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
},
|
||||
server: {
|
||||
proxy: {
|
||||
|
Reference in New Issue
Block a user