how to intercept 401 in App.vue on mounted hook Vuejs (Quasar)

Viewed 549

I have a serviceRoot file that construct the axios instance. I'm using different services also to trigger the API depending of the data. (I will not speak about these services here).

My problem is, I want to kick people when they come back on the website after their tkn is expired. So I would like to put a code in the App.vue file on the mounted hook, because it's for me the best moment to check if the user gets a 401 error when he tries to load the website directly on the /profil url.

import VueCookies from 'vue-cookies'
import Conf from '../../conf.js'
export default class HttpClient {
  headers = {
    Authorization: '',
    'Content-Type': '',
    Accept: ''
  }
  service = {}
  method = ''
  userId = ''

  constructor() {
    const tkn = VueCookies.get('tkn')
    const token = `Bearer ${tkn}`
    // eslint-disable-next-line prettier/prettier
    this.headers.Authorization = token
    this.headers['Content-Type'] = 'application/json;charset=utf-8'
    this.headers.Accept = 'application/json'

    this.service = Axios.create({
      baseURL: Conf.api_url,
      headers: this.headers,
      data: this.data
    })
    this.service.interceptors.response.use(this.handleSuccess, this.handleError)
    console.log(this.handleSuccess, this.handleError)
  }

  handleSuccess(response) {
    return response
  }

  handleError(error) {
    return Promise.reject(error)
  }

  request = async (axios, config) => {

    if (
      config.method === 'POST' ||
      config.method === 'PUT' ||
      config.method === 'DELETE' ||
      config.method === 'GET'
    ) {
      console.log('trigger api')
    }

    const request = {
      method: config.method || this.method,
      url: config.url,
      data: config.data,
      headers: config.headers ? config.headers : this.headers,
      params: config.params,
      responseType: config.responseType
    }

    if (config.headers) {
      request.headers = {
        ...request.headers,
        ...config.headers
      }
    }
    axios.defaults.headers.post['Content-Type'] = 'multipart/form-data'
    try {
      const response = await axios(request)
      return response.data
    } catch (error) {

      throw error
    }
  }
} 

But with that kind of serviceRoot I really don't know how to do that in the app.vue, I tried this:

<script>
import { defineComponent } from '@vue/composition-api'
import Axios from 'axios'

export default defineComponent({
  name: 'App',
  data() {
    return {
      layout: 'div'
    }
  },
  created() {
    console.log('CREATED')
    Axios.interceptors.response.use(undefined, function(err) {
      return new Promise(function(resolve, reject) {
        if (err.status === 401 && err.config && !err.config.__isRetryRequest) {
          console.log('DISPATCH')
          // this.$store.dispatch(logout)
        }
        throw err
      })
    })
  }
})
</script>

But in that case, the Axios.interceptors doen't work with the first file so I wont work. I tried to import HttpClient from './services/serviceRoot' but the browser says: Uncaught TypeError: Super expression must either be null or a function.

I can kick directly on serviceRoot after the throw error, but I can't diferency 401's errors (because there are diffents kind of 401s and I wanna only kick people with wront token on the load of the app.

Thanks

1 Answers

Interceptor should go in main.js file

axios.interceptors.response.use(response => {
  return response;
}, error => {
  if (error && error.message === 'Request failed with status code 401') {
    localStorage.removeItem('user');
     router.push({name: loginPageName});
  }
Related