From 3737f689f9b1935299ab8e6dc13122cddff37d47 Mon Sep 17 00:00:00 2001 From: Rekord <1324596506@qq.com> Date: Tue, 11 Apr 2023 21:55:20 +0800 Subject: [PATCH 1/2] perf: implement authorization throtting --- src/service/api/index.js | 106 +++++++++++++++++++++++++-------------- 1 file changed, 68 insertions(+), 38 deletions(-) diff --git a/src/service/api/index.js b/src/service/api/index.js index ca2903c..f2d1d6e 100644 --- a/src/service/api/index.js +++ b/src/service/api/index.js @@ -1,53 +1,83 @@ -import axios from 'axios'; -import { API_BASE_URL } from '@/config/api'; -import api from '@/service/api/api'; +import axios from "axios"; +import { API_BASE_URL } from "@/config/api"; +import api from "@/service/api/api"; // 创建axios实例 const instance = axios.create({ - baseURL: API_BASE_URL, // 你的API服务器地址 - timeout: 5000 // 请求超时时间 + baseURL: API_BASE_URL, // 你的API服务器地址 + timeout: 5000, // 请求超时时间 }); +let requestQueue = []; // 请求队列 + +let isRefreshing = false; // 是否正在刷新token + +// 添加一个等待鉴权的请求到队列中 +function addRequestToQueue(config, resolve, reject) { + requestQueue.push({ config, resolve, reject }); +} + +// 处理队列中的请求,并清空队列 +function processRequestQueue() { + requestQueue.forEach(({ config, resolve, reject }) => { + // 重新发送原始请求 + instance(config) + .then((response) => resolve(response)) + .catch((error) => reject(error)); + }); + requestQueue = []; +} + // 请求拦截器 instance.interceptors.request.use( - config => { - // 在请求发送之前做些什么 - const token = localStorage.getItem('jwt') - if (token) { - // 设置Authorization头部 - config.headers.authorization = token + (config) => { + // 在请求发送之前做些什么 + const token = localStorage.getItem("jwt"); + if (token) { + // 设置Authorization头部 + config.headers.authorization = token; + } + return config; + }, + (error) => { + // 处理请求错误 + return Promise.reject(error); } - return config; - }, - error => { - // 处理请求错误 - return Promise.reject(error); - } ); // 响应拦截器 instance.interceptors.response.use( - response => { - // 对响应数据做些什么 - const token = response.headers.authorization - if (token) { - localStorage.setItem("jwt", token) - } - return response; - }, - async error => { - // 处理响应错误 - if (error.response.status === 401 && error.response.data.status === 402) { - const user = JSON.parse(sessionStorage.getItem("user")); - // 发送登录请求以获取新的 token - await api.loginUser(user.username, user.password); - // 重新发送原始请求 - return instance(error.config); - } else { - // 如果没有响应错误,则抛出原始异常 - return Promise.reject(error); + (response) => { + // 对响应数据做些什么 + const token = response.headers.authorization; + if (token) { + localStorage.setItem("jwt", token); + } + return response; + }, + async (error) => { + // 处理响应错误 + if ( + error.response.status === 401 && + error.response.data.status === 402 + ) { + if (!isRefreshing) { + isRefreshing = true; + const user = JSON.parse(sessionStorage.getItem("user")); + // 发送登录请求以获取新的 token + await api.loginUser(user.username, user.password); + isRefreshing = false; + processRequestQueue(); + } + + return new Promise((resolve, reject) => { + addRequestToQueue(error.config, resolve, reject); + }); + } else { + // 如果没有响应错误,则抛出原始异常 + return Promise.reject(error); + } } - } ); -export default instance; \ No newline at end of file +export default instance; From 63d14193934e73510ac0670f925bbc6061fc5e58 Mon Sep 17 00:00:00 2001 From: Rekord <1324596506@qq.com> Date: Tue, 11 Apr 2023 22:05:06 +0800 Subject: [PATCH 2/2] refactor: take api outer to level up extensibility --- src/plugins/apiPlugin.js | 88 +++------------------------------------- src/service/api/api.js | 74 +++++++++++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 85 deletions(-) diff --git a/src/plugins/apiPlugin.js b/src/plugins/apiPlugin.js index bae963b..325ec3a 100644 --- a/src/plugins/apiPlugin.js +++ b/src/plugins/apiPlugin.js @@ -1,92 +1,16 @@ // apiPlugin.js -import { post, get, asyncPost } from "@/service/request"; -import { - USER_LOGIN_URL, - USER_REGISTER_URL, - USER_UPDATE_URL, - USER_SEARCH_URL, - RELATION_UPDATE_URL, - RELATION_ADD_URL, - GROUP_ADD_URL, - GROUP_SEARCH_URL, -} from "@/config/api"; -import { OPENAI_API_KEY, OPENAI_MAKING_REQUEST } from "@/config/openai"; import api from "@/service/api/api"; export default { install(Vue) { Vue.prototype.$api = { loginUser: api.loginUser, - registerUser(username, password) { - return post(USER_REGISTER_URL, { - username, - password, - }); - }, - updateRelation(requestId, acceptId, type, status) { - return post(RELATION_UPDATE_URL, null, { - requestId, - acceptId, - type, - status, - }).then((res) => { - if (!res.data.status == 200) { - console.log("network error"); - } - }); - }, - addRelation(rel, type) { - return post(RELATION_ADD_URL, null, { - acceptId: rel.id, - type, - status: rel.status, - }).then((res) => { - if (res.data.status == 200) { - rel.status = 0; - } else { - console.log("network error"); - } - }); - }, - updateUserOrAddGroup(type, avatarPath, name, password) { - const url = type == 0 ? USER_UPDATE_URL : GROUP_ADD_URL; - return post(url, { - avatarPath, - name, - password, - }); - }, - searchUserOrSearchGroup(isGroup, name) { - return get(isGroup ? GROUP_SEARCH_URL : USER_SEARCH_URL, { - name, - }); - }, - async generateResponse(content) { - const headers = { - "Content-Type": "application/json", - Authorization: `Bearer ${OPENAI_API_KEY}`, - }; - - const data = { - model: "gpt-3.5-turbo", - messages: [{ role: "user", content }], - temperature: 0.7, - }; - - try { - console.log("Waiting for chatgpt answer..."); - const response = await asyncPost( - OPENAI_MAKING_REQUEST, - {}, - data, - { headers } - ); - console.log("show chatgpt response..."); - return response.data.choices[0].message.content; - } catch (error) { - console.error(error); - } - }, + registerUser: api.registerUser, + updateRelation: api.updateRelation, + addRelation: api.addRelation, + updateUserOrAddGroup: api.updateUserOrAddGroup, + searchUserOrSearchGroup: api.searchUserOrSearchGroup, + generateResponse: api.generateResponse, }; }, }; diff --git a/src/service/api/api.js b/src/service/api/api.js index d026da4..45e07f4 100644 --- a/src/service/api/api.js +++ b/src/service/api/api.js @@ -9,12 +9,80 @@ import { GROUP_ADD_URL, GROUP_SEARCH_URL, } from "@/config/api"; +import { OPENAI_API_KEY, OPENAI_MAKING_REQUEST } from "@/config/openai"; export default { - loginUser: function(username, password) { + loginUser: (username, password) => { return post(USER_LOGIN_URL, { username, password, }); - } -} \ No newline at end of file + }, + registerUser: (username, password) => { + return post(USER_REGISTER_URL, { + username, + password, + }); + }, + updateRelation: (requestId, acceptId, type, status) => { + return post(RELATION_UPDATE_URL, null, { + requestId, + acceptId, + type, + status, + }).then((res) => { + if (!res.data.status == 200) { + console.log("network error"); + } + }); + }, + addRelation: (rel, type) => { + return post(RELATION_ADD_URL, null, { + acceptId: rel.id, + type, + status: rel.status, + }).then((res) => { + if (res.data.status == 200) { + rel.status = 0; + } else { + console.log("network error"); + } + }); + }, + updateUserOrAddGroup: (type, avatarPath, name, password) => { + const url = type == 0 ? USER_UPDATE_URL : GROUP_ADD_URL; + return post(url, { + avatarPath, + name, + password, + }); + }, + searchUserOrSearchGroup: (isGroup, name) => { + return get(isGroup ? GROUP_SEARCH_URL : USER_SEARCH_URL, { + name, + }); + }, + generateResponse: async (content) => { + const headers = { + "Content-Type": "application/json", + Authorization: `Bearer ${OPENAI_API_KEY}`, + }; + + const data = { + model: "gpt-3.5-turbo", + messages: [{ role: "user", content }], + temperature: 0.7, + }; + + try { + console.log("Waiting for chatgpt answer..."); + const response = await asyncPost(OPENAI_MAKING_REQUEST, {}, data, { + headers, + }); + console.log("show chatgpt response..."); + return response.data.choices[0].message.content; + } catch (error) { + console.error(error); + } + }, +};