Omar Hussein
Omar Hussein

Reputation: 1147

How to add interceptor function to Axios?

Alright, So I'd like to add a response interceptor to my global axios config, that retries a request once if it gets a 401 error, after refreshing the token.

This is my current global axios config:

import axios from "axios";

export default axios.create({
  baseURL: process.env.REACT_APP_API,
  headers: {
    "content-type": "application/json"
  },
  responseType: "json"
});

Now I've did research my issue has been addressed here, however, I'm not aware how I can attach or use the interceptor function in the answer there to my axios config file (after I edit it to my needs ofc) the interceptor function looks like this:

createAxiosResponseInterceptor() {
    const interceptor = axios.interceptors.response.use(
        response => response,
        error => {
            // Reject promise if usual error
            if (errorResponse.status !== 401) {
                return Promise.reject(error);
            }

            /* 
             * When response code is 401, try to refresh the token.
             * Eject the interceptor so it doesn't loop in case
             * token refresh causes the 401 response
             */
            axios.interceptors.response.eject(interceptor);

            return axios.post('/api/refresh_token', {
                'refresh_token': this._getToken('refresh_token')
            }).then(response => {
                saveToken();
                error.response.config.headers['Authorization'] = 'Bearer ' + response.data.access_token;
                return axios(error.response.config);
            }).catch(error => {
                destroyToken();
                this.router.push('/login');
                return Promise.reject(error);
            }).finally(createAxiosResponseInterceptor);
        }
    );
}

Many thanks!

Upvotes: 3

Views: 9559

Answers (2)

ibtsam
ibtsam

Reputation: 1710

I think you need to call your intercept creator with custom instance of axios. You can do it as

const instance = axios.create({
 baseURL: process.env.REACT_APP_API,
 headers: {
 "content-type": "application/json"
 },
 responseType: "json"
});

and pass this instance to createAxiosResponseInterceptor as

createAxiosResponseInterceptor(instance);

You would have to change your createAxiosResponseInterceptor to receive this instance as

function createAxiosResponseInterceptor(instance) {
const interceptor = instance.interceptors.response.use(
    response => response,
    error => {
        // Reject promise if usual error
        if (errorResponse.status !== 401) {
            return Promise.reject(error);
        }

        /* 
         * When response code is 401, try to refresh the token.
         * Eject the interceptor so it doesn't loop in case
         * token refresh causes the 401 response
         */
        instance.interceptors.response.eject(interceptor);

        return instance.post('/api/refresh_token', {
            'refresh_token': this._getToken('refresh_token')
        }).then(response => {
            saveToken();
            error.response.config.headers['Authorization'] = 'Bearer ' + response.data.access_token;
            return instance(error.response.config);
        }).catch(error => {
            destroyToken();
            this.router.push('/login');
            return Promise.reject(error);
        }).finally(createAxiosResponseInterceptor);
    }
);
}

and of course export as

export default instance;

Hope it helps

Upvotes: 1

kidney
kidney

Reputation: 3093

If I understand the problem correctly, you need to invoke the interceptor creator function on your custom axioms instance. So something like:

import axios from "axios";

const instance = axios.create({
  baseURL: process.env.REACT_APP_API,
  headers: {
    "content-type": "application/json"
  },
  responseType: "json"
});

function createAxiosResponseInterceptor(axiosInstance) {
    const interceptor = axiosInstance.interceptors.response.use(
        response => response,
        error => {
            // Reject promise if usual error
            if (errorResponse.status !== 401) {
                return Promise.reject(error);
            }

            /*
             * When response code is 401, try to refresh the token.
             * Eject the interceptor so it doesn't loop in case
             * token refresh causes the 401 response
             */
            axiosInstance.interceptors.response.eject(interceptor);

            return axiosInstance.post('/api/refresh_token', {
                'refresh_token': this._getToken('refresh_token')
            }).then(response => {
                saveToken();
                error.response.config.headers['Authorization'] = 'Bearer ' + response.data.access_token;
                return axiosInstance(error.response.config);
            }).catch(error => {
                destroyToken();
                this.router.push('/login');
                return Promise.reject(error);
            }).finally(createAxiosResponseInterceptor);
        }
    );
}

createAxiosResponseInterceptor(instance);

export default instance;

And make the createAxiosResponseInterceptor function take the axios instance as a parameter.

Upvotes: 3

Related Questions