Search code examples
vue.jsaxiosnuxt.jstokenasyncdata

Using axios in Nuxt asyncData lose token on browser refresh


I am getting the meta tags from an API using asyncData in Axios in Nuxt but my problem is that the meta description have to be set server side to appear in the code.
So I added the following my nuxt page :

asyncData(context) {
  return context.$axios
    .get('/api/house', {
      headers: {
        'X-AUTH-TOKEN': '######',
        'Content-Type': 'application/json',
      },
    })
    .then((res) => {
      return { fetchedData: res.data.page.meta }
    })
},

At first the meta description is there in the code but if I refresh the browser I lose my token.

I tried to add it in the nuxt.config.js with:

axios: {
  headers: {
    common: {
      'X-AUTH-TOKEN': '###################',
      'Content-Type': 'application/json',
    },
  },
},

Like this I was thinking that every axios GET request will have the token server side without being lost but it doesn't work. So I tried to set up an axios interceptor making an axios.js and adding it in nuxt.config.js :

plugins: [
  { src: '~/plugins/axios.js' },  
]

my axios.js :

import axios from 'axios'

const AUTH_TOKEN = '#######################'

axios.defaults.headers.common['Authorization'] = AUTH_TOKEN

axios.defaults.headers.post['Content-Type'] = 'application/json'

But the result is still the same everytime I refresh my Nuxt page, the token disappears and because I use asyncData the page does not render.

How can I set up my meta description with asyncData and add my token to every GET request even if I refresh my browser?

EDIT

Here is how i make my cliend side request in my nuxt page for the meta tags:

<script>
export default {
  layout: 'house',

  asyncData(context) {
    return context.$axios
      .get('/api/house', {
        headers: {
          'X-AUTH-TOKEN': '### TOKEN HARDCODED ###',
          'Content-Type': 'application/json',
        },
      })
      .then((res) => {
        return { fetchedData: res.data.page.meta }
      })
  },

  data() {
    return {
      route: 'house',
      fetchedData: [],
    }
  },
  head() {
    return {
      title: this.fetchedData.title,
      meta: [
        { charset: 'utf-8' },
        { name: 'viewport', content: 'width=device-width, initial-scale=1' },
        { hid: 'description', name: 'description', content: this.fetchedData.description },
      ],
    }
  },
}
</script>

Solution

  • Alright, so here is a codesandbox to show you the working example with a test fake API: https://codesandbox.io/s/so-async-data-nuxt-axios-get-f4y3v?file=/pages/index.vue

    And here is the actual interesting code

    <template>
      <div>
        <p>fetched data below</p>
        <p>{{ fetchedData }}</p>
      </div>
    </template>
    
    <script>
    export default {
      async asyncData({ $axios, $config: { secureToken } }) { // import your env varibles here
        const response = await $axios.$get( // $get shortcut, https://axios.nuxtjs.org/usage#-shortcuts
          'https://jsonplaceholder.typicode.com/todos/1',
          {
            headers: {
              'X-AUTH-TOKEN': secureToken,
              'Content-Type': 'application/json',
            },
          }
        )
        return { fetchedData: response }
      },
    }
    </script>
    

    Of course, you can hardcode the secureToken but here, I showed you how to use an env variable.

    This is a part of the nuxt.config.js file

    export default {
      publicRuntimeConfig: {
        secureToken: process.env.SECURE_TOKEN,
      },
      ...
    }
    

    You should put into a .env file.

    SECURE_TOKEN="### TOKEN HARDCODED ###"
    

    It will of course need to be blacklisted from the .gitignore (default behavior btw). I committed it for example purposes, do not expose it publicly. Use env variables on your server ! :)

    Once this is working, you could look into some axios global configuration. Let me know if this one works properly before going ahead.