nuxt.js

How to reinitiate/resend a request with $fetch like Axios?


I have a onResponseError interceptor in which I would like to resend the original request after updating its headers with a new valid token. With Axios this was possible like this:

const originalRequestConfig = error.config;
// [...] Update the headers
return $axios.request(originalRequestConfig);

How do I achieve this with $fetch?

I want to:

This should not be an unusual scenario 🤔


Solution

  • 
    // USAGE
    <script lang="ts" setup>
    const { data, pending, error, refresh } = useFetch('/pages', {})
    </script>
    
    // @/composables/useCustomFetch.ts
    import type { UseFetchOptions } from 'nuxt/app'
    import { defu } from 'defu'
    
    export function useCustomFetch<T> (url: string, options: UseFetchOptions<T> = {}) {
        const config = useRuntimeConfig()
        const { isSignedIn, getToken, setToken } = useAuthStore()
    
        const defaults: UseFetchOptions<T> = {
            baseURL: config.public.apiBaseUrl,
            key: url,
            server: false,
            retry: 1,
            retryStatusCodes: [401],
            retryDelay: 500, // can safely delete this
    
            onRequest({ options }) {
               options.headers = isSignedIn
                  ? { Authorization: `Bearer ${getToken()}` } // send token
                  : {}
            },
    
            async onResponseError({ response, options }) {
               if (response.status === 401) {
                 await useFetch('/auth/refresh', {
                   baseURL: config.public.apiBaseUrl,
                   method: 'POST',
                   server: false,
                   credentials: 'include',
    
                   onResponse({ response }) {
                     setToken(response._data.token) // store token
                   },
             },
           )
          }
         }
        }
    
        const params = defu(options, defaults)
    
        return useFetch(url, params)
     }