Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@nuxtjs/axios - adding interceptor #73

Closed
silverbackdan opened this issue Jul 19, 2017 · 6 comments
Closed

@nuxtjs/axios - adding interceptor #73

silverbackdan opened this issue Jul 19, 2017 · 6 comments

Comments

@silverbackdan
Copy link
Contributor

silverbackdan commented Jul 19, 2017

If I add an interceptor in middleware, it works fine from the client side, but for SSR the interceptor is not used when an Axios request is in a component's asyncData method.

When logging I can see that the interceptor is called first, and then when the request in async data is called, I can't log any output from within the interceptor signifying that a 403 status code has been detected.

In my middleware:

app.$axios.interceptors.response.use(
    undefined,
    (error) => {
      if (error.response && error.response.status === 403 && !error.response.config.isRetry) {
        // try to refresh the token
        return app.$axios.post(
          '/refresh_token',
          {
            _action: store.getters.getApiUrl('refresh_token')
          },
          {
            baseURL: null
          }
        )
          .then((res) => {
            // We were successful with our refreshing - so time to retry the request
            store.commit('setAuthUser', jwtDecode(res.data.token))
            error.response.config.isRetry = true
            return app.$axios(error.response.config)
          })
          .catch((err) => {
            store.commit('setAuthUser', null)
            if (err.response.status === 500) {
              return Promise.reject(err)
            }
            // Unsuccessful responses from our middleware will result in cookies being unset anyway
            // Some of these requests can be carried out without a token so we should retry anyway
            error.response.config.isRetry = true
            return app.$axios(error.response.config)
          })
      }
      return Promise.reject(error)
    }
  )

called from asyncData

let pageUrl = store.getters.getApiUrl(slug)
    return app.$axios.get(pageUrl)
      .then((res) => {
        if (res.statusCode) {
          throw new AxiosError(res.statusCode, res.message)
        }
        if (typeof res.data !== 'object' || !res.data.id) {
          throw new AxiosError(404, '')
        }
        let newData = Object.assign({}, masterData, res.data)
        if (store.getters.getAuthUser() && store.getters.hasRole('ROLE_ADMIN')) {
          newData.patchUrl = store.getters.getApiUrl('pages/' + (slug || 'home'))
          store.commit('cms/initEndpoint', newData.patchUrl)
        }
        return loadExtras(newData, slug, store, error)
      })
      .catch((err) => {
        if (err.response) {
          error({
            statusCode: err.response.status,
            message: (err.response.status === 404 ? 'Page could not be found' : err.response.data.message)
          })
        } else {
          if (typeof err === 'string') {
            error({
              statusCode: 500,
              message: err
            })
          } else {
            error({
              statusCode: 500,
              message: 'An error occurred'
            })
          }
        }
      })

This works when I just change page as a user though. Am I going about this the wrong way?

This question is available on Nuxt.js community (#c39)
@silverbackdan
Copy link
Contributor Author

Just moved the interceptor to directly before the get request within asyncData and that doesn't work either strangely enough - also if I use axios directly - I don't think this can be an issue with this plugin after seeing that.

@silverbackdan
Copy link
Contributor Author

Actually, this is an error in the plugin.

// Don't throw unhandled promises in SSR context
    return this.app._nuxt.error.call({$options: this.app}, {
      message: error.message,
      statusCode: error.statusCode
    })

Because in SSR the error isn't passed I can't catch it and do whatever I want. How can we get around this one?

@pi0
Copy link
Member

pi0 commented Jul 24, 2017

@silverbackdan In latest commit, I've entirely removed that auto error handling logic. Would be nice having your comments on it before next release :)

@silverbackdan
Copy link
Contributor Author

@pi0 Ooo I quite like that :) I didn't know if there was a reason why the promise wasn't rejected on server-side before but it is nice still having the standardised status and message. It'd certainly work for my needs still!

@pi0
Copy link
Member

pi0 commented Jul 24, 2017

Thanks for your review. Actually i think the problem with handled promises should be fixed on Nuxt itself because both fetch and asyncData are being called before actual Vue rendering.

@silverbackdan
Copy link
Contributor Author

That's much better, I'll update to the latest commit tomorrow morning. Thanks for taking the time on this module.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants