A.R.SEIF
A.R.SEIF

Reputation: 873

Return Response When First request failed And Try In Second Request

I try to explain the problem.in App.js I have Function getUser .when call this function.in first request get 401 error . For this reason in axios.interceptors.response I receive error 401.At this time, I receive a token and repeat my request again.And it is done successfully.But not return response in Function getUser.
I have hook for authentication and send request.

import React from "react";
import axios from "axios";

const API_URL = "http://127.0.0.1:4000/api/";

function useJWT() {

  axios.interceptors.request.use(
    (request) => {
      request.headers.common["Accept"] = "application/json";
      console.log("request Send ");
      return request;
    },
    (error) => {
      return Promise.reject(error);
    }
  );
  axios.interceptors.response.use(
    (response) => {
      console.log("answer = ", response);
      return response;
    },
    (error) => {
      if (error?.response?.status) {
        switch (error.response.status) {
          case 401:
            refreshToken().then((responseTwo) => {
              return
                sendPostRequest(
                  error.response.config.url
                    .split("/")
                    .findLast((item) => true)
                    .toString(),
                  error.response.config.data
              );
            });
            break;
          case 500:
            // Actions for Error 500
            throw error;
          default:
            console.error("from hook interceptor => ", error);
            throw error;
        }
      } else {
        // Occurs for axios error.message = 'Network Error'
        throw error;
      }
    }
  );

  const refreshToken = () => {
    const token = localStorage.getItem("refresh");
    return axios
      .post(API_URL + "token", {
        token,
      })
      .then((response) => {
        if (response.data.access) {
          localStorage.setItem("access", response.data.access);
        }
        if (response.data.refresh) {
          localStorage.setItem("refresh", response.data.refresh);
        }
        return response.data;
      });
  };

  function login(email, password) {
    return axios
      .post(API_URL + "login", {
        email,
        password,
      })
      .then((response) => {
        if (response.data.access) {
          localStorage.setItem("access", response.data.access);
        }
        if (response.data.refresh) {
          localStorage.setItem("refresh", response.data.refresh);
        }
        return response.data;
      });
  }

  const sendPostRequest = (url, data) => {
    console.log(300);
    const token = localStorage.getItem("access");
    axios.defaults.headers.common["jwt"] = token;

    return axios.post(API_URL + url, {
      data,
    });
  };

  const logout = () => {
    const token = localStorage.getItem("refresh");
    return axios
      .delete(API_URL + "logout", {
        token,
      })
      .then((response) => {
        localStorage.removeItem("access");
        localStorage.removeItem("refresh");
      });
  };

  return {
    login,
    logout,
    refreshToken,
    sendPostRequest,
  };
}

export default useJWT;


In App.js ,I want to repeat the same request again if a 401 error is issued when I read the user information. The request is successfully repeated but does not return the value.
When first request fail response is return equals null . and in catch when receive 401 error i am send second request but not return response.
I send request below code .
const getUser = () => {
 console.log(12);
 return sendPostRequest("user");
  };

  useEffect(() => {
    let token = localStorage.getItem("access");
    console.log("token = ", token);
    if (token != null) {
      //Here I have done simulation for 401 error
     localStorage.setItem("access", "");
       getUser()
         .then((response) => {
           console.log("response 1= ", response);
         })
    .catch((exception) => {
      console.log("exception = ", exception.toString());
    })
    .then((response) => {
      console.log("response 2= ", response);
    });
} else {
  navigate("/login");
}
 }, []);

Best regards.

Upvotes: 1

Views: 1314

Answers (2)

A.R.SEIF
A.R.SEIF

Reputation: 873

I find anwser for this question.
When error 401 occurs then create new Promise
I Wrote this code.

case 401:
        return new Promise((resolve, reject) => {
          refreshToken().then((responseTwo) => {
            resolve(
              sendPostRequest(
                error.response.config.url
                  .split("/")
                  .findLast((item) => true)
                  .toString(),
                error.response.config.data
              )
            );
          });
        });

Upvotes: 1

zhyp
zhyp

Reputation: 329

I didn't fully understand what exactly you want to do here. But if you are looking to retry when 401 happens, you could use axios-retry to do it for you.

I'll pass the basics, but you can look more into what this does.

// First you need to create an axios instance
const axiosClient = axios.create({
  baseURL: 'API_URL',
  // not needed
  timeout: 30000
});

// Then you need to add this to the axiosRetry lib
axiosRetry(axiosClient, {
  retries: 3,
  // Doesn't need to be this, it can be a number in ms
  retryDelay: axiosRetry.exponentialDelay,
  retryCondition: (error) => {
  // You could do this way or try to implement your own
    return error.response.status > 400 
    // something like this works too.
    // error.response.status === 401 || error.response.status >= 500;
  }
});

Just like in your code, we need to use interceptors if you want to avoid breaking your page, otherwise you can use try catch to catch any errors that may happen in a request.

// It could be something like this, like I said, it's not really needed.
axiosClient.interceptors.response.use(
  (success) => success,
  (err) => err
);

And finally, you could use the axiosClient directly since it now has your API_URL, calling it like this axiosClient.post('/user').

More or less that's it, you should just debug this code and see what is causing the return value to be null. I would change these then/catch to be an async/await function, it would be more readable making your debugging easier.

axios-retry example if you didn't understand my explanation.

Upvotes: 1

Related Questions