首页 > 其他分享 >拦截器

拦截器

时间:2023-07-01 18:37:15浏览次数:26  
标签:code return url data 拦截器 const config

import { FetchBlobType } from '@/services/api' import { message } from 'antd' import axios, { AxiosHeaders, AxiosRequestConfig, AxiosRequestHeaders, AxiosResponse, InternalAxiosRequestConfig } from 'axios' import _ from 'lodash' import { X_API_KEY, cloud_doman, perfixApiWeb } from '../../config/const' import { LocalKey, RedirectKey, TokenKey, getCookie, removeCookie } from './cookies' import { codes, getCodeMessage, zhCnMsg } from './errorCodes' import uuid from './uuid'
// 字符串转hash const strToHash = (str: string) => { let hash = 0 let chr if (str.length === 0) { return hash } for (let i = 0; i < str.length; i++) { chr = str.charCodeAt(i) hash = (hash << 5) - hash + chr hash |= 0 } return hash }
// 生成请求key const getRequestKey = (config: IInternalAxiosRequestConfig) => { let { url, method, data, params, responseType, fetchBlobType } = config data = typeof data === 'string' ? JSON.parse(data) : data // 文件分片上传的接口 const isBlobUpload = fetchBlobType === FetchBlobType.upload let UUID = isBlobUpload ? uuid() : 'uuid' // 把请求转为字符串 const requestStr = `${UUID}_${method}_${url}_${params ? JSON.stringify(params) : JSON.stringify(data)}` // 设置请求key const requestKey = strToHash(requestStr) return requestKey }
export type IResponse<D> = { message: string data: D code: keyof typeof zhCnMsg x_filename?: string } export type GptResponse = { messages: string prompt_tokens: number completion_tokens: number total_tokens: number }
type IAxiosRequestHeaders = | ({ 'X-REQUEST-ID': string 'X-LANGUAGE': string 'X-API-KEY': string } & AxiosRequestHeaders) | AxiosHeaders
interface IInternalAxiosRequestConfig extends InternalAxiosRequestConfig { allowDuplicate?: boolean // 允许重复请求 promptMessage?: boolean // 需要提示消息 fetchBlobType?: FetchBlobType // 二进制流文件请求方式 headers: IAxiosRequestHeaders }
/** * allowDuplicate {boolean} false 允许重复请求 * retry {number} 1 重试次数 * retryDelay {number} 2 重试时间(单位s) */ // 请求队列 const requestQueue = new Map()
const instance = axios.create({ baseURL: perfixApiWeb, timeout: 10 * 1000, allowDuplicate: true, promptMessage: false, } as IInternalAxiosRequestConfig)
// // 请求 const request = async <T>(config: AxiosRequestConfig): Promise<IResponse<T>> => { return instance(config) // return instance.request<IResponse<T>>(config) }
// 请求拦截器 instance.interceptors.request.use( (config: IInternalAxiosRequestConfig) => { const { baseURL, url, headers, allowDuplicate } = config // console.log('请求拦截', config) const token = getCookie(TokenKey) const lang = getCookie(LocalKey) if (token) { headers[TokenKey] = token headers['X-REQUEST-ID'] = uuid() headers['X-API-KEY'] = X_API_KEY headers['X-LANGUAGE'] = lang } else { redirect() return config } // 允许重复请求 if (!allowDuplicate) { return config }
// 重复请求逻辑 const requestKey = getRequestKey(config) const controller = new AbortController() config.signal = controller.signal // 判断请求队列是否存在相同请求 if (requestQueue.has(requestKey)) { controller.abort() } else { requestQueue.set(requestKey, controller) } return config }, (error) => { // 请求错误 console.log('请求错误', error) return Promise.reject(error) }, )
// 响应拦截器 instance.interceptors.response.use( (response: AxiosResponse) => { // console.log('响应拦截', response) const { data, config } = response const { code } = data const { promptMessage, responseType, fetchBlobType } = config as IInternalAxiosRequestConfig const requestKey = getRequestKey(config) requestQueue.delete(requestKey) const msg = getCodeMessage(code)
// 响应成功 code === 0 if (_.isNumber(code) && codes.SUCCESS === code) { promptMessage && message.success(msg) } if (_.isNumber(code) && ![codes.SUCCESS, codes.REQUEST_AGAIN].includes(code)) { message.error(msg) } // token 失效 if ([codes.CODE_TOKEN_ERROR].includes(code)) { setTimeout(() => { redirect() }, 200) } if (responseType === 'blob') { // 流文件 - 下载 const filename = response.headers['x-filename'] if (data.type === 'application/json') { return { code: 21000, message: msg, data, } } else { return { code: 0, message: msg, data, x_filename: filename, } } } return data }, async (error) => { // 响应 code !== 0 // console.log('响应错误', error) const { config, code } = error const requestKey = getRequestKey(config) requestQueue.delete(requestKey) // 超时 => 请求重试 if (error.message.indexOf('timeout') !== -1) { if (config.allowDuplicate) { const { retry = 1, retryDelay = 2, retryCount = 0 } = config // 延时请求 const delay = new Promise<void>((resolve) => { setTimeout(() => { resolve() }, retryDelay * 1000) }) // 重试次数 && 当前重试次数未超过最大重试次数 if (retry && retryCount < retry) { config.retryCount = retryCount + 1 // console.log(`[请求异常] 尝试重新请求 => [${config.url}] => 第 ${config.retryCount} 次`) // 重新发起请求 return delay.then(function () { return request(config) }) } } cancelAllRequest() } // 取消不报错 if (!['ERR_CANCELED'].includes(code)) { message.error(error.message || 'error') return Promise.reject(error) } }, )
// 取消所有请求 const cancelAllRequest = () => { requestQueue.forEach((controller) => { controller.abort() }) requestQueue.clear() return true }
// 重定向 - 清除 token const redirect = () => { cancelAllRequest() removeCookie(TokenKey) window.location.href = getCookie(RedirectKey) || cloud_doman }
const get = <T>(url = '', params = {}, config = {}) => { const iconfig = { method: 'get', url, params, ...config, } return request<T>(iconfig) }
const post = <T>(url = '', data = {}, config = {}) => { const iconfig = { method: 'post', url, data, ...config, } return request<T>(iconfig) }
const put = <T>(url = '', data = {}, config = {}) => { const iconfig = { method: 'put', url, data, ...config, } return request<T>(iconfig) }
const destroy = <T>(url = '', data = {}, config = {}) => { const iconfig = { method: 'delete', url, data, ...config, } return request<T>(iconfig) }
const upload = <T>(url = '', data = {}, config = {}) => { const iconfig = { method: 'post', url, data, headers: { 'Content-Type': 'multipart/form-data', }, timeout: 200 * 1000, ...config, } return request<T>(iconfig) }
export default { get, post, put, delete: destroy, upload, cancelAllRequest, }

标签:code,return,url,data,拦截器,const,config
From: https://www.cnblogs.com/liiann/p/17519681.html

相关文章

  • 过滤器,拦截器,AOP的区别
    SpringAOPAOP(AspectOrientProgramming),直译过来就是面向切面编程,AOP是一种编程思想,是面向对象编程(OOP)的一种补充。面向切面编程,实现在不修改源代码的情况下给程序动态统一添加额外功能的一种技术,AOP可以拦截指定的方法并且对方法增强,而且无需侵入到业务代码中,使业务与非业......
  • 拦截器的配置以及执行顺序
    在SpringBoot中,拦截器的执行顺序可以通过InterceptorRegistry对象的addInterceptor()方法按照添加的顺序进行配置。默认情况下,拦截器的执行顺序是按照它们添加到拦截器注册表中的顺序执行的。也就是说,先添加的拦截器会先执行,后添加的拦截器会后执行importorg.springframework......
  • Feign客户端的拦截器
    importfeign.RequestInterceptor;importfeign.RequestTemplate;importlombok.extern.slf4j.Slf4j;importorg.springframework.stereotype.Component;importorg.springframework.web.context.request.RequestContextHolder;importorg.springframework.web.context.r......
  • 过滤器和拦截器 (持续更新)
     实现拦截器的前置postHandle和后置处理器 如果postHandler抛了异常。threadlocal的clear方法就无法实现,所以可以放在后指处理器里面使用从代码可以看出,拦截器接口有三个方法,分别的作用是:preHandle方法:叫做预处理方法,本方法在控制器方法(MyController的方法)之前执行,用户......
  • 11. 拦截器
    11.1、拦截器的配置SpringMVC中的拦截器用于拦截控制器方法的执行SpringMVC中的拦截器需要实现HandlerInterceptorSpringMVC的拦截器必须在SpringMVC的配置文件中进行配置:<beanclass="com.atguigu.interceptor.FirstInterceptor"></bean><refbean="firstInterceptor"></ref......
  • MybatisPlus拦截器配置
    /***配置mp的分页插件(拦截)*/@ConfigurationpublicclassMybatisPlusConfig{@BeanpublicMybatisPlusInterceptormpInterceptor(){MybatisPlusInterceptormybatisPlusInterceptor=newMybatisPlusInterceptor();mybatisPlusInterceptor.......
  • Angular中的HTTP请求】- 拦截器 HttpInterceptor 详解
    原文: 【Angular中的HTTP请求】-拦截器HttpInterceptor详解__老杨_的博客-CSDN博客通过学习HttpClient的工作机制,我们知道对于HTTP请求,HttpClient实际上是构建了一个链式的处理流程: 在HttpBackend的处理流程中请求被发出。在HttpBackend的前面可以设置多个的拦截器,对请......
  • mybatis拦截器实现数据权限
    前端的菜单和按钮权限都可以通过配置来实现,但很多时候,后台查询数据库数据的权限需要通过手动添加SQL来实现。比如员工打卡记录表,有id,name,dpt_id,company_id等字段,后两个表示部门ID和分公司ID。查看员工打卡记录SQL为:selectid,name,dpt_id,company_idfromt_record当一个总......
  • 拦截器应用举例之权限拦截器
    1. 项目需求  68只有经过登录的用户方可访问处理器,否则,将返回“无权访问”提示。本例的登录,由一个 JSP 页面完成。即在该页面里将用户信息放入 session 中。也就是说,只要访问过该页面,就说明登录了。没访问过,则为未登录用户。2. 项目实现  68使用拦截器检查登录的用户是不......
  • springboot 拦截器配置
      创建目录 interceptor——MyInterceptor.java文件,该文件实现 HandlerInterceptor接口 MyInterceptor.java文件实现 HandlerInterceptor接口代码如下: 代码案例:(已验证cookie为案列)importorg.springframework.beans.factory.annotation.Value;importorg.springframework.......