vue3 请求响应拦截

  

import axios, { AxiosInstance } from 'axios';
import { ElMessage, ElMessageBox } from 'element-plus';
import { MessageType } from 'element-plus/lib/el-message/src/types';
import { Base64 } from 'js-base64';
import { IRequests, ServiceOptions, SvcParams, whiteListUrl } from '../model/requst';
import { RESPONSETYPE } from '../model/requst';
import store from '../store';
import { getTenant, getToken } from './auth';

// 预防 出现option跨域请求
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
let invalidationMark = true;

const servicesOptions:ServiceOptions = {
  mesRequest: {
    timeout: 60000,
    baseURL: `${import.meta.env.VITE_APP_BASE_API}`,
    // withCredentials: true
  }
}

function permissionHandler() {
  if (invalidationMark) {
    invalidationMark = false;
    ElMessageBox.alert(
      '你已被登出,可以取消继续留在该页面,或者重新登录',
      '确定登出',
      {
        confirmButtonText: '确定',
        callback: () => {
          store.dispatch('FedLogOut').then(() =>{
            location.reload(); // 莫名其妙代码
          });
          invalidationMark = true;
        }
      }
    )
  }
}

function arrayBufferHandler(responseData: Iterable<number>) {
  const enc = new TextDecoder('utf-8');
  const errorData = JSON.parse(enc.decode(new Uint8Array(responseData)));
  return errorData;
}

function messageHandler(msg: string, type: MessageType) {
  ElMessage({
    message: msg,
    type: type,
    duration: 3000
  });
}

function decorateService(service: AxiosInstance) {
  // 请求拦截
  service.interceptors.request.use(
    // 请求配置
    (config) => {
      const clientId = import.meta.env.VITE_APP_CLIENT_ID;
      const clientSecret = import.meta.env.VITE_APP_CLIENT_SECRET;
      const isToken = config.headers['X-isToken'] === false ? config.headers['X-isToken'] : true;
      const isTenant = config.headers['X-isTenant'] === false ? config.headers['X-isTenant'] : true
        && import.meta.env.VITE_APP_IS_MULTI_TENANT_TYPE !== "NONE";
      isToken && (config.headers.token = 'Bearer ' + getToken());
      isTenant && (config.headers.tenant = getTenant());
      config.headers['Authorization'] = `Basic ${Base64.encode(`${clientId}:${clientSecret}`)}`;
      return config;
    },
    (error) => {
      Promise.reject(error);
    }
  );
  service.interceptors.response.use(
    (response) => {
      const responseData = response.data;
      const url = response.config.url?.substring(0, response.config.url.lastIndexOf('/'));
      const isWhite = url && whiteListUrl.includes(url);   
      const contentType = response.headers['content-type'];
      const isJson = contentType && contentType === 'application/json; charset=UTF-8';
      if (responseData.code === 0 || !isJson) {
        return Promise.resolve(responseData);
      }
      !isWhite && messageHandler(responseData.msg, 'error');
      return Promise.reject(responseData);
    },
    (error) => {
      const responseType = error.config?.responseType;
      const errorData = responseType === RESPONSETYPE.ARRAYBUFFER ? arrayBufferHandler(error.response.data) : error.response?.data;
      const status = error.response?.status
      switch(status) {
        case 500:
        case 501:
        case 502:
        case 503:
          messageHandler('服务暂未启动,请稍等一会儿再试~~', 'error');
          return Promise.reject(Error('服务暂未启动'));
        case 401:
          return permissionHandler();
        default:
          const msg = errorData?.msg || errorData?.errorMsg || '系统内部异常,请联系网站管理员';
          messageHandler(msg, 'error');
          return Promise.reject(errorData);
      }
    }
  )
}

function getServices(options: ServiceOptions): IRequests {
  const requests:IRequests = {};
  Object.keys(options).forEach((svcName) => {
    requests[svcName] = axios.create(options[svcName as SvcParams]);
    decorateService(requests[svcName]);
  });
  return requests;
}

export default getServices(servicesOptions);

  

// requst的接口

import type { AxiosInstance, AxiosRequestConfig } from "axios";

export const whiteListUrl = [
  '/componentBom/batchImport',
  '/componentBom/importBomBasic',
  '/componentBom/importMaterial',
  '/componentBom/importBomRebar',
  '/stackLoadPlan/planImport'
] 

export const RESPONSETYPE = {
  ARRAYBUFFER: 'arraybuffer',
  BLOB: 'blob',
  DOCUMENT: 'document',
  JSON: 'json',
  STREAM: 'stream',
  TEXT: 'text',
}

export interface ServiceOptions {
  mesRequest: AxiosRequestConfig;
}

export interface IRequests {
  [axiosSvcName: string]: AxiosInstance
}

export type SvcParams = 'mesRequest';

  

上一篇:DRF认证源码、频率、过滤、自定义异常类、Response


下一篇:arcgis api for flex 开发入门(二)map 的创建