Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Axios - Interceptors not working on request error - 401 code

Tags:

reactjs

axios

I have a simple react app that is using a third API to fetch data. Before making any requests, a token must be retrieved in order to use it in the headers. This token is created by using the same API by passing the client id and secret id - the API is Artsy API. This token has an expiration date so this API must be requested if the token doesn't not exist. After getting the token, then I can call other requests without a problem.

I have set up the API requests in a separate file, like so: Apis.js

import Axios from 'axios';
const baseURL = 'https://api.artsy.net/api';

// set up xap-token and set tot default headers
const instance = Axios.create({
    baseURL: baseURL + '/tokens/xapp_token',
    params: {
        'client_id': process.env.CLIENTID,
        'client_secret': process.env.CLIENTSECRET
    }
});

instance.interceptors.request.use(undefined, err => {
    const status = err.response ? err.response.status : null;
    console.log("auth",err.response)

    if(status === 401){
        console.log("auth",err.response)
        return 'hello'
        // this.getAuthToken();
    }
});

export default{

    getArtworks: function(){
        return new Promise((resolve, reject) => {
            instance.get(baseURL + '/artworks')
            .then(res => {
                resolve(res)
            })
            .catch(err => {
                reject(err);
            });
        });
    },

    getArtists: function(){
        return new Promise((resolve, reject) => {
            instance.get(baseURL + '/artists')
            .then(res => {
                resolve(res)
            })
            .catch(err => {
                reject(err);
            });
        });

    },

    getTest: function(){
        return 'hello';
    }
};

Not really sure how to use the create and interceptors, but I created an Axios instance. So the idea is to create some sort of middleware, create an instance and then use it as an interceptor if there is a request on that error. If there is, then apply the token to that instance and proceed with the request, retry. Also not sure how to set the the token in the instance.

So far I'm getting a 401 error in the getArtists method, this api gets called when the page loads, it's under componentDidMount.

App.jsx

import React, { Component } from 'react';
import Apis from './utils/Api';
import Gallery from './components/Gallery';

class App extends Component{
    constructor(props){
        super(props);
        this.state = {
            artWorks: []
        }
    }

    componentDidMount = () => {
        // Apis.getArtists();
        Apis.getArtists().then(res => {
            console.log(res)
            // this.setState({
            //     artWorks: res.data
            // })
        });
    }

    render(){
        return(
            <div>
                <Gallery artists={this.state.artWorks}/>
            </div>
        )
    }
}

export default App;

This is the api doc links for authentication.

Can anybody help? not really sure how to use the instance as a "middleware"? new to Axios. I would like to avoid 3rd library middleware, I prefer to learn in a manual way than using 3rd libraries. Your help will be much appreciated

Update:

I was able to get this somewhat working, i modified the instance.interceptor:

instance.interceptors.response.use(undefined, err => {
    const status = err.response ? err.response.status : null;
    if(status === 401){
        console.log("auth",err.response)

        instance.post(err.config.authURL, err.config.auth).then(res => {
            let token = res.data.token;
            err.config.headers['X-XAPP-Token'] = token;
            console.log('calling',err.response)
            return instance.request(err.config)
        });
    }

    // return Promise.reject(err);
});

But I'm getting undefined in the getArtists response. Not sure what's going on here. Here is a screenshot of the console:

enter image description here

like image 510
medev21 Avatar asked Oct 26 '25 00:10

medev21


1 Answers

You should use instance.interceptors.response rather than instance.interceptors.request .

Because the request interceptor is called before Ajax request send. I think the response interceptor is actually what you want here.


  1. About BaseURL, you should set like below
const instance = Axios.create({
    baseURL: 'https://api.artsy.net/api'
})
// because you set the baseURL of the instance
// this will request url https://api.artsy.net/api/artworks
instance.get('/artworks')
  1. About 401 Error you get, from the api doc you give.I think you should request to get the token before your app start.
instance.post('tokens/xapp_token').then(res => {
  /* here is the response
{
  "type" : "xapp_token",
  "token" : "...",
  "expires_at" : "2014-09-05T12:39:09.200Z"
}
  */

  // you can set common request headers like this
  // or use request interceptors here to set headers
  // then every request you sent by instance after will have X-XAPP-Token header
  instance.defaults.headers.common['X-XAPP-Token'] = res.token
})

Actually err.config.headers['X-XAPP-Token'] = token; this code will not affect the request headers.

like image 142
MinimalistYing Avatar answered Oct 27 '25 16:10

MinimalistYing



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!