DEV Community

Cover image for Quasar - SSR and using cookies

Quasar - SSR and using cookies

Tobias Mesquita on October 30, 2019

Getting Quasar’s SSR cookie plugin working with other libraries and services. Table Of Contents 1 Introduction 2 The Problem...
Collapse
 
flyingboy007 profile image
Abhilash • Edited

I changed the axios boot file like below by adding Vue.mixin instead of Vue.prototype. But now when I try to access this.$axios.post() in .vue component its throwing TypeError: Cannot read property 'post' of undefined. So the global mixin is not passing into components. I simply copied the mixin logic from here.

( didnt try the injection part as written in this post as I got stuck before
that part and trying to understand whats happening :))

import Vue from 'vue'
import axios from 'axios'
import { Cookies } from 'quasar'

Vue.mixin({
  beforeCreate () {
    const options = this.$options
    if (options.axios) {
      this.$axios = options.axios
    } else if (options.parent) {
      this.$axios = options.parent.$axios
    }
  }
})
export default function ({ app, ssrContext, store, router }) {
  const axiosInstance = axios.create({
    baseURL: 'http://lvh.me:3000',
    headers: {
      'Content-Type': 'application/json'
    }
  })
  const cookies = process.env.SERVER
    ? Cookies.parseSSR(ssrContext)
    : Cookies
  axiosInstance.interceptors.request.use(config => {
    const userString = cookies.get('user')
    if (userString) {
      // setup vuex
      store.$db().model('users').create({
        data: userString.user
      })
      // setup headers
      config.headers.Authorization = `bearer ${userString.token}`
    }
    return config
  }, error => {
    return Promise.reject(error)
  })

  axiosInstance.interceptors.response.use(
    response => response,
    error => {
      // if login route no need to reload
      if (error.response.status === 401 && router.currentRoute.path !== '/login') {
        //  store.$db().model('users').logout()
        cookies.remove('user')
        location.reload()
      }
      return Promise.reject(error)
    }
  )
  app.$axios = axiosInstance
}
Enter fullscreen mode Exit fullscreen mode

Any insights on what could be the issue here?

Collapse
 
tobymosque profile image
Tobias Mesquita

this would be:

app.axios = axiosInstance // without the `$`
Enter fullscreen mode Exit fullscreen mode
Collapse
 
flyingboy007 profile image
Abhilash

Thank you.

Collapse
 
eladc profile image
Elad Cohen

Great article! Can you please show your final implementation on Github repo?

Collapse
 
tobymosque profile image
Tobias Mesquita

really sorry, i missed your comment.:
gitlab.com/TobyMosque/quasar-couch...

Collapse
 
flyingboy007 profile image
Abhilash

I think this link is not for this article as this code is missing there. Could you please share the correct link if possible?

Thread Thread
 
tobymosque profile image
Tobias Mesquita

ops, i didn't created a repo to this article, mostly because this is a simplified version of what i do.

Normally, I didn't access the cookies directly, i use vuex-persistedstate as a middleware.
but u can access the Cookies directly, there is nothing wrong with this approach
github.com/TobyMosque/qpanc/blob/m...

And here the axios part:
github.com/TobyMosque/qpanc/blob/m...

I'll try to create a repo to this article at the weekend.

Thread Thread
 
flyingboy007 profile image
Abhilash

Ok. Thank you for the support

Collapse
 
omnichronous profile image
Mitko Georgiev

This guide has been invaluable, thank you. Just one thing I'm trying to puzzle out - what is the purpose of the beforeCreate() code here? Is there a reason to prefer this over injecting the Axios instance in the Vue prototype?

Collapse
 
tobymosque profile image
Tobias Mesquita

Vue.prototype is shared between all Vue instances, what will result in a single axios instance to all Vue instances (a singleton).

But in that particular case, a singleton can mess with our autentication logic, since that is being handled into the axios interceptor and this reads the token from the Cookies plugin, what isn't a singleton, what can lead to a data leak.

Collapse
 
mikeevstropov profile image
mikeevstropov

Thank you man!

Collapse
 
antalszabo profile image
AntalSzabo

Thank you for the excellent article! It would be nice to have this added to the Quasar documentation (if it is not there already), as it is rather square one if you want to implement SSR. I'd have one small remark, under 5 Navigation guards, in ./src/router/index.js, I had to switch context.router.beforeEnter to context.router.beforeEach. As far as I know, there is no global guard beforeEnter now in Vue Router, I'm not sure for older versions.

Collapse
 
tobymosque profile image
Tobias Mesquita

probably a small typo, thx for report.

Collapse
 
ibrainventures profile image
ibrainventures

Also a great Article and perfect understandable written.
Thank you for sharing your know how.

Collapse
 
jerabix profile image
JeRabix

how can I get app context for call my other service?

Collapse
 
tobymosque profile image
Tobias Mesquita

I didn't understood u question