首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >umi请求拦截器响应的刷新令牌

umi请求拦截器响应的刷新令牌
EN

Stack Overflow用户
提问于 2020-08-10 21:02:36
回答 1查看 1.2K关注 0票数 3

我使用令牌作为授权,当令牌过期时,我希望使用刷新令牌创建一个新的令牌。我可以使用axios库做到这一点,但是我不知道如何使用umi request来做到这一点。有人将下面给出的代码示例翻译成umi请求拦截器示例吗?

这个axios拦截器响应我的刷新令牌操作。

代码语言:javascript
复制
  let isRefreshing: boolean = false;
  let failedQueue: any = [];

  const processQueue = (error: any, token: any = null) => {
    failedQueue.forEach((prom: any) => {
      if (error) {
        prom.reject(error);
      } else {
        prom.resolve(token);
      }
    });

    failedQueue = [];
  };

axios.interceptors.response.use(
    async response => {
      return response;
    },
    async error => {
      debugger;
      const originalRequest = error.config;
      if (error.response) {
        const status = error.response.status;
        const refreshToken = getStoredUserAuth().refreshToken;
        if (status === 401 && !originalRequest._retry) {
          if (isRefreshing) {
            return new Promise(function(resolve, reject) {
              failedQueue.push({ resolve, reject });
            })
              .then(token => {
                originalRequest.headers["Authorization"] = "Bearer " + token;
                return axios(originalRequest);
              })
              .catch(err => {
                return Promise.reject(err);
              });
          }

          originalRequest._retry = true;
          isRefreshing = true;

          return new Promise(function(resolve, reject) {
            refreshAccessToken(refreshToken)
              .then(response => {
                if (response.status === 200) {
                  if (response.data.token) {
                    setAuthStatus(response.data);
                    axios.defaults.headers.common["Authorization"] =
                      "Bearer " + response.data.token;
                    originalRequest.headers["Authorization"] =
                      "Bearer " + response.data.token;
                  }
                  processQueue(null, response.data.token);
                  resolve(axios(originalRequest));
                } else {
                  throw new Error();
                }
              })
              .catch(err => {
                //console.log(err);
                failedQueue = [];
                setUnauthStatus();
                source.cancel("Session time out");
                processQueue(err, null);
                reject(err);
              })
              .then(() => {
                isRefreshing = false;
              });
          });
        }
      } else {
        debugger;
        errorHandler(error);
      }
      return Promise.reject(error);
    }
  );

我用的是ant design pro V5版本,所以我试着用umi请求刷新令牌,但是我做不到,因为在axios库中,我不能写umi请求,我不能建立它的逻辑。那么,任何人都可以为umi request编写相同的示例(axios.interceptors.response)吗?

代码语言:javascript
复制
const requestInterceptors = (url: string, options: RequestOptionsInit) => {
  if (tokenService.check()) {
    const headers = {
      'Content-Type': 'application/x-www-form-urlencoded',
      'Accept': 'application/x-www-form-urlencoded',
      'Authorization': `Bearer ${tokenService.parse()?.token}`,
    };
    return {
      url,
      options: { ...options, headers },
    };
  }
  return {
    url,
    options: { ...options },
  };
};

const responseInterceptors = (response: Response, options: RequestOptionsInit) => {

// I could'nt this part for refresh token like axios interceptors. I need help for that

return response;
}

export const request: RequestConfig = {
  errorHandler,
  requestInterceptors: [requestInterceptors],
  responseInterceptors: [responseInterceptors]
};

umi request github link for documentation

EN

回答 1

Stack Overflow用户

发布于 2021-04-05 23:23:20

这是我在umi-request/ant-design-pro中处理刷新令牌的解决方案,不需要queues,工作起来非常棒。

代码语言:javascript
复制
// Neccesary imports
import type { RequestConfig } from 'umi';
import { request as requestUmi } from 'umi';
import type {
  RequestInterceptor,
  RequestOptionsInit,
  ResponseError,
} from 'umi-request';
import Reqs from 'umi-request';
import merge from 'lodash/merge';
import cloneDeep from 'lodash/cloneDeep';

// My personal type definitions
namespace API {
  export interface LoginResult {
    access: string;
    refresh: string;
  }
}

// Part 1: "Simple" Error Handler =))
const errorHandler = (error: ResponseError) => {
  console.log('HTTP ERROR', error);
  throw error;
};

// Part 2: Request Interceptors, (use this instead of "headers" directly in request config)
const requestInterceptor: RequestInterceptor = (url, options) => {
  return {
    url,
    options: merge(cloneDeep(options), {
      headers: { Authorization: `Bearer ${jwt.getAccess()}` },
    }),
  };
};

// Part 3: Response Interceptos
const { cancel } = Reqs.CancelToken.source();
let refreshTokenRequest: Promise<API.LoginResult> | null = null;
const responseInterceptor = async (
  response: Response,
  options: RequestOptionsInit
) => {
  const accessTokenExpired = response.status === 401;
  if (accessTokenExpired) {
    try {
      if (!refreshTokenRequest) {
        refreshTokenRequest = refreshAccessToken(jwt.getRefresh());
      }
      // multiple requests but "await"ing for only 1 refreshTokenRequest, because of closure
      const res = await refreshTokenRequest;
      if (!res) throw new Error();
      if (res.access) jwt.saveAccess(res.access);
      if (res.refresh) jwt.saveRefresh(res.refresh); // for ROTATE REFRESH TOKENS
      return requestUmi(
        response.url,
        merge(cloneDeep(options), {
          headers: { Authorization: `Bearer ${res.access}` },
        })
      );
    } catch (err) {
      jwt.removeAccess();
      jwt.removeRefresh();
      cancel('Session time out.');
      throw err;
    } finally {
      refreshTokenRequest = null;
    }
  }

  return response;
};

export const request: RequestConfig = {
  errorHandler,
  // This would fuck the refresh token logic, use requestInterceptors instead,
  // because jwt.getAccess() will not being called everytime, but only the first time => lead to stale access token
  // headers: { Authorization: `Bearer ${jwt.getAccess()}` },

  // Handle refresh token (old): https://github.com/ant-design/ant-design-pro/issues/7159#issuecomment-680789397
  // Handle refresh token (new): https://gist.github.com/paulnguyen-mn/8a5996df9b082c69f41bc9c5a8653533
  requestInterceptors: [requestInterceptor],
  responseInterceptors: [responseInterceptor],
};

还发布了here

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63340790

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档