question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Interceptors] Creating an API client with automatic token refresh functionality

See original GitHub issue

Hi!

We talked about this yesterday over on the Nuxt discord’s #nuxt3 channel, but since it’s more of an ohmyfetch thing, I decided to create the issue here instead of the nuxt/framework repo.

We’re currently firing up a development effort for a new Nuxt3 project in our company (we’ve previously used Nuxt2 in some projects). Axios was the preferred way of doing API requests previously but since ohmyfetch is now the recommended choice, I thought of rewriting our API client wrapper to use ohmyfetch instead of Axios.

I’m sure the problem is familiar to most if not all of you: how to write an API client that can automatically refresh your access tokens behind the scenes? This is pretty much our previous solution that uses Axios’ interceptors:

const createAPIClient = () => {
  const apiClient = axios.create({ headers, baseUrl })
  
  apiClient.interceptors.request.use(config => {
    const accessTokens = authStore.tokens  // { accessToken: '', refreshToken: '' }
    if (tokens) {
      config.headers.common.Authorization = `Bearer ${tokens.accessToken}`
    }
    return config
  })
  
  apiClient.interceptors.response.use(
    response => response,
    async error => {
      const originalRequest = error.config
      
      // .isRetry is a non-axios property we use to differentiate the actual request from the one we're firing in this interceptor
      if (error.response?.status === 401 && !originalRequest.isRetry) {
        originalRequest.isRetry = true
        try {
          // fetch new tokens from our API
          const refreshToken = authStore.refreshToken
          const { data } = axios.post('/our/nuxt/server-middleware/auth/route/that/proxies/to/our/api/', { refreshToken })
          
          // simplified for brevity
          setNewAccessTokensToStore(data)
          
          // retry the original request
          originalRequest.headers = { ...originalRequest.headers, Authorization: `Bearer ${data.refreshToken}` }
          return apiClient(originalRequest)
        } catch (refreshError) {
          return Promise.reject(refreshError)
        }  
      }
    }
  )
  
  return apiClient
}

Historically we’ve done this by creating one larger doRequest function that gets called recursively, but it was refactored to use interceptors.

I’d like to replicate this functionality using ohmyfetch, so that I could do something like:

const $customFetch = () => {
  const client = $fetch.create({
    baseURL: 'https://example.com',
    async onRequest(ctx => {
      // like apiClient.interceptors.request.use
    }),
    async onResponseError(ctx => {
      // like apiClient.interceptors.response.use
    })
  })

// in any Nuxt3 component
const { data, pending, error, refresh } = await useAsyncData('getSomeData', () => $customFetch('/some/endpoint/in/our/api'))

and the access tokens get set to request headers and possibly refreshed automatically.

I was checking out ohmyfetch’s interceptors, but apparently they don’t return anything, only functioning as hooks where you can set up logging or do something else, instead of acting as sort of middleware like Axios’ counterparts. This leads me to the conclusion that this probably isn’t currently possible with ohmyfetch? It’s no problem to use the recursive approach we had previously, but I feel that this is a bit of a shortcoming with the current interceptors.

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:8
  • Comments:8 (1 by maintainers)

github_iconTop GitHub Comments

6reactions
AscaLcommented, Oct 6, 2022

Hi, I’m having a similar flow/issue with Nuxt 3 and was wondering if:

  • Support for this feature (interceptors with behaviour similar to axios) is coming.
  • There is any new functionality that allows me to handle this at this time.
  • Should I develop using an alternative solution (maybe nuxt-alt/http as suggested)

Sorry to bother but I’m starting a project with Nuxt 3 at work. I’m just trying to avoid any issues. Thanks for all the hard work!

Cheers

5reactions
pi0commented, May 10, 2022

Thanks for the feedback @evfoxin @attevaltojarvi

As a summary what I could understand is missing:

  • Allow chaining fetch requests using interceptors
  • Expose internal type for FetchContext

Actually it is currently possible to achieve this by modification to the context but it is probably more convenience to allow chaining.

Read more comments on GitHub >

github_iconTop Results From Across the Web

[Interceptors] Creating an API client with automatic ... - GitHub
Historically we've done this by creating one larger doRequest function that gets called recursively, but it was refactored to use interceptors.
Read more >
Using Axios interceptors for refreshing your API token.
I'm using Redis to store the token and refresh token received from the API as you can see in the examples. Obvious code...
Read more >
Axios Interceptors tutorial with Refresh Token example
In this tutorial, I will show you how to work with Axios Interceptors: eject, error, 401 status, handling infinite loop and Refresh Token...
Read more >
Handling Access and Refresh Tokens using Axios Interceptors.
I will put an Access token and Refresh token to LocalStorage using localStorageService. · Change Authorization header with the new Access token ......
Read more >
Handle Refresh Tokens with Axios - JavaScript in Plain English
The client must get a new token to continue working with other services. We have many solutions to get new tokens automatically. One...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found