2

I am building a Vue frontend with Rails backend.

On frontend I am using Axios and I have set these interceptors for authentication:

import axios from 'axios'

const API_URL = 'http://localhost:3000'

const securedAxiosInstance = axios.create({
  baseURL: API_URL,
  withCredentials: true,
  headers: {
    'Content-Type': 'application/json'
  }
})

const plainAxiosInstance = axios.create({
  baseURL: API_URL,
  withCredentials: true,
  headers: {
    'Content-Type': 'application/json'
  }
})

securedAxiosInstance.interceptors.request.use(config => {
  const method = config.method.toUpperCase()
  if (method !== 'OPTIONS' && method !== 'GET') {
    config.headers = {
      ...config.headers,
      'X-CSRF-TOKEN': localStorage.csrf
    }
  }
  return config
})

securedAxiosInstance.interceptors.response.use(null, error => {
  if (error.response && error.response.config && error.response.status === 401) {
    // If 401 by expired access cookie, we do a refresh request
    return plainAxiosInstance.post('/refresh', {}, { headers: { 'X-CSRF-TOKEN': localStorage.csrf } })
      .then(response => {
        localStorage.csrf = response.data.csrf
        localStorage.signedIn = true
        // After another successfull refresh - repeat original request
        let retryConfig = error.response.config
        retryConfig.headers['X-CSRF-TOKEN'] = localStorage.csrf
        return plainAxiosInstance.request(retryConfig)
      }).catch(error => {
        delete localStorage.csrf
        delete localStorage.signedIn
        // redirect to signin if refresh fails
        location.replace('/')
        return Promise.reject(error)
      })
  } else {
    return Promise.reject(error)
  }
})

export { securedAxiosInstance, plainAxiosInstance }

On main.js I am making them available this way:

import VueAxios from 'vue-axios'
import { securedAxiosInstance, plainAxiosInstance } from './axios'
Vue.use(VueAxios, {
  secured: securedAxiosInstance,
  plain: plainAxiosInstance
})
new Vue({
  el: '#app',
  router,
  store,
  securedAxiosInstance,
  plainAxiosInstance,
  render: h => h(App)
})

And in components I can successfully use them like:

this.$http.secured.get('/items')

The problem is that I am unable to use them in store where I get: Cannot read property 'secured' of undefined"

I tried in store among others:

import { securedAxiosInstance, plainAxiosInstance } from '../axios'

    const store = new Vuex.Store({
        secured: securedAxiosInstance,
        plain: plainAxiosInstance,
    .....

What is the correct way to do it?

4
  • How are you trying to use them in store? Commented Nov 29, 2019 at 13:43
  • I have tried a lot of combinations in store and modules, including the same imports I am doing in main.js. But none of them works. Commented Nov 29, 2019 at 13:50
  • 1
    You can try this._vm.$http.secured.get('/items') or pass the vue instance as payload to your mutation/action Commented Nov 29, 2019 at 13:57
  • Yes that fixed it.. If you put it in an answer I will accept it. Can you also please explain it? Thanks! Commented Nov 29, 2019 at 14:13

1 Answer 1

4

You can use this._vm inside the store which refers to the Vue instance of the current application.

So in your case:

this._vm.$http.secured.get('/items')

As alternative you can pass the Vue instance as payload to your mutation/action, like:

this.$store.commit('myMutation',this)

Sign up to request clarification or add additional context in comments.

1 Comment

I'm having the same issue but using this gets me a typeError 'cannot read property then of undefined.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.