Axios 拦截器重试发送 FormData

3
我想为包含FormData数据的请求创建“重试”功能。当JWT令牌过期时,将进行重试,我的第二个请求(重试请求)不包含任何数据。
思路:
const axiosInstance = axios.create();

  /**
   * Before each request, we'll add a possible retry if the
   * request need a refreshed token
   */
  axiosInstance.interceptors.request.use((request) => {
    if (typeof _.get(request, ['retried']) === 'undefined') {
      request.retried = false;
    }

    return request;
  });

/**
   * After a request with an error, we'll check if the error is a token not refreshed.
   * If we didn't already tried to refresh, we'll just fallback to the errorHandler function
   */
  axiosInstance.interceptors.response.use(null, async (error) => {
    const statusCode = _.get(error, ['response', 'data', 'statusCode']);
    const message = _.get(error, ['response', 'data', 'message']);
    const { config: request = {} } = error;

    if (statusCode === 401 && !request.retried) {
      try {
        const newTokens = await refreshTokens();
        request.retried = true;
        _.set(request, ['headers', 'authorization'], newTokens.accessToken);
        return axiosInstance.request(request);
      } catch (e) {
        return error;
      }
    }
    return error;
  });

请求:

  const formData = new FormData();
  formData.append('name', name);
  formData.append('file', fs.createReadStream(file.path));

  axiosInstance.post(
      'http://localhost/upload',
      formData,
      {
        headers: {
          ...formData.getHeaders(),
          authorization: tokens.accessToken
        }
      }
    );

如果我的 Token 过期了,请求将会失败,然后拦截器将刷新我的 Token,并使用新的头部 Authorization 再次尝试相同的请求。然而,在服务器端,收到的负载(payload)总是 null。

嘿,你能解决这个问题了吗? - Puzzero
1
很遗憾,正如下面回答中@tnarik所说,一旦formData(它是一个流)被使用,就不能再次使用。您必须找到一种方法来重新创建formData,以便能够将其添加到下一个请求中:/编辑:至少这就是我在这个问题上的进展。也许有人对此有更好的解决方案! - Chop
使用拦截器的另一种解决方案是创建一个端点,仅检查您的令牌,并在被拦截的请求具有formData时在interceptors.request.use钩子中发送请求。你可以这样说:“如果这个请求有formData,请让我联系我的后端并检查我的令牌是否正确,如果不正确,则刷新并继续”。 - Chop
3
我所做的是,在发送请求之前检查令牌是否过期,如果是,则重新获取令牌。这只适用于formData请求。谢谢! - Puzzero
不用客气。在stackoverflow上创建自己的问题和使用代码进行回答,这可能会在某个时刻帮助到某个人!;) - Chop
同样的问题,兄弟。 - LeoPucciBr
2个回答

2
据我所知,在重试时需要再次添加formData(我认为这是由于数据作为流添加并在请求期间被消耗,因此新的重试无法消耗已经被消耗的流)。您可以查看request.data以了解我的意思。

0

您可以通过配置参数传递表单数据:

axiosInstance.post(
  'http://localhost/upload',
  {},
  {
    data: formData, // <---- pass it here
    headers: {
      ...formData.getHeaders(),
      authorization: tokens.accessToken
    }
  }
);

你能详细说明一下吗?我尝试了你的想法,但是无法使其工作,因为它将表单作为数据发送到服务器并搞乱了一切。 - LeoPucciBr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接