This simplifies fetching data, but what if you have a multitude of APIs that all require authentication? Adding headers to each call gets tedious fast.

Enter interceptors.

To add global interceptors, we'll build a custom composable wrapper around $fetch. This is especially valuable when your API calls consistently need authorization headers.

As a foundation, let's use the same project from my previous blog post on Authentication in Nuxt 3.

let's start by creating a new composable under composable folder composables/useAuthFetch.ts

import type { UseFetchOptions } from \\'nuxt/app\\';const useAuthFetch = (url: string | (() => string), options: UseFetchOptions = {}) => {  const customFetch = $fetch.create({    baseURL: \\'https://dummyjson.com\\',    onRequest({ options }) {      const token = useCookie(\\'token\\');      if (token?.value) {        console.log(\\'[fetch request] Authorization header created\\');        options.headers = options.headers || {};        options.headers.Authorization = `Bearer ${token.value}`;      }    },    onResponse({ response }) {      console.info(\\'onResponse \\', {        endpoint: response.url,        status: response?.status,      });    },    onResponseError({ response }) {      const statusMessage = response?.status === 401 ? \\'Unauthorized\\' : \\'Response failed\\';      console.error(\\'onResponseError \\', {        endpoint: response.url,        status: response?.status,        statusMessage,      });      throw showError({        statusCode: response?.status,        statusMessage,        fatal: true,      });    },  });  return useFetch(url, {    ...options,    $fetch: customFetch,  });};export default useAuthFetch;

Explanation:

you can find out more about the interceptors here

Now, whenever you need to fetch data from an authenticated API, simply use useAuthFetch instead of useFetch, and the authorization will be handled seamlessly.

\\\"Custom

When you inspect the network call you can see the baseUrl is correct and the Authorization header is present

Logging

In my interceptors, I have added some logs this can be useful if you have tools like Sentry in your application.

How to add Sentry to Nuxt: https://www.lichter.io/articles/nuxt3-sentry-recipe/

in the onRequest interceptor you could add a breadcrumb to sentry

import * as Sentry from \\'@sentry/vue\\';Sentry.addBreadcrumb({        type: \\'http\\',        category: \\'xhr\\',        message: ``,        data: {          url: `${options.baseURL}${request}`,        },        level: \\'info\\',});

if your backend returns a tracingId you could also add a tag and context with sentry to link errors with an endpoint

onResponseError you could add context breadcrumb and tag

import * as Sentry from \\'@sentry/vue\\';Sentry.setContext(\\'http-error\\', {   endpoint: response?.url,   tracingId: 123,   status: response?.status,});Sentry.addBreadcrumb({ type: \\'http\\', category: \\'xhr\\', message: ``, data: {  url: response?.url,  status_code: response?.status, }, level: \\'error\\',});Sentry.setTag(\\'tracingId\\', \\'123\\');

replace tracingIdwith whatever custom tracing log your backend returns

","image":"http://www.luping.net/uploads/20241003/172795752666fe8a16368ef.png","datePublished":"2024-11-08T14:15:37+08:00","dateModified":"2024-11-08T14:15:37+08:00","author":{"@type":"Person","name":"luping.net","url":"https://www.luping.net/articlelist/0_1.html"}}
"If a worker wants to do his job well, he must first sharpen his tools." - Confucius, "The Analects of Confucius. Lu Linggong"
Front page > Programming > Custom fetch with Interceptors and logs in nuxt 3

Custom fetch with Interceptors and logs in nuxt 3

Published on 2024-11-08
Browse:762

If you've used Nuxt you've probably encountered the handy useFetch composable:

This simplifies fetching data, but what if you have a multitude of APIs that all require authentication? Adding headers to each call gets tedious fast.

Enter interceptors.

To add global interceptors, we'll build a custom composable wrapper around $fetch. This is especially valuable when your API calls consistently need authorization headers.

As a foundation, let's use the same project from my previous blog post on Authentication in Nuxt 3.

let's start by creating a new composable under composable folder composables/useAuthFetch.ts

import type { UseFetchOptions } from 'nuxt/app';

const useAuthFetch = (url: string | (() => string), options: UseFetchOptions = {}) => {
  const customFetch = $fetch.create({
    baseURL: 'https://dummyjson.com',
    onRequest({ options }) {
      const token = useCookie('token');
      if (token?.value) {
        console.log('[fetch request] Authorization header created');
        options.headers = options.headers || {};
        options.headers.Authorization = `Bearer ${token.value}`;
      }
    },
    onResponse({ response }) {
      console.info('onResponse ', {
        endpoint: response.url,
        status: response?.status,
      });
    },
    onResponseError({ response }) {
      const statusMessage = response?.status === 401 ? 'Unauthorized' : 'Response failed';
      console.error('onResponseError ', {
        endpoint: response.url,
        status: response?.status,
        statusMessage,
      });
      throw showError({
        statusCode: response?.status,
        statusMessage,
        fatal: true,
      });
    },
  });

  return useFetch(url, {
    ...options,
    $fetch: customFetch,
  });
};

export default useAuthFetch;

Explanation:

  • useAuthFetch: Our custom composable. It takes the same arguments as useFetch.
  • customFetch: Creates a customized $fetch instance with interceptors.
  • baseURL: By using baseURL option, ofetch prepends it for trailing/leading slashes and query search params for baseURL using ufo:
  • onRequest: This interceptor runs before every fetch call. It grabs the token from a cookie and adds the Authorization header if a token is present.
  • onResponse: Runs after a successful fetch, providing logging.
  • onResponseError: Handles fetch errors, logs details, and throws an error using showError (assuming you have this defined).
  • return useFetch(...): Finally, we call the original useFetch, but pass in our customFetch to handle the actual requests.

you can find out more about the interceptors here

Now, whenever you need to fetch data from an authenticated API, simply use useAuthFetch instead of useFetch, and the authorization will be handled seamlessly.

Custom fetch with Interceptors and logs in nuxt 3

When you inspect the network call you can see the baseUrl is correct and the Authorization header is present

Logging

In my interceptors, I have added some logs this can be useful if you have tools like Sentry in your application.

How to add Sentry to Nuxt: https://www.lichter.io/articles/nuxt3-sentry-recipe/

in the onRequest interceptor you could add a breadcrumb to sentry

import * as Sentry from '@sentry/vue';

Sentry.addBreadcrumb({
        type: 'http',
        category: 'xhr',
        message: ``,
        data: {
          url: `${options.baseURL}${request}`,
        },
        level: 'info',
});

if your backend returns a tracingId you could also add a tag and context with sentry to link errors with an endpoint

onResponseError you could add context breadcrumb and tag

import * as Sentry from '@sentry/vue';

Sentry.setContext('http-error', {
   endpoint: response?.url,
   tracingId: 123,
   status: response?.status,
});
Sentry.addBreadcrumb({
 type: 'http',
 category: 'xhr',
 message: ``,
 data: {
  url: response?.url,
  status_code: response?.status,
 },
 level: 'error',
});
Sentry.setTag('tracingId', '123');

replace tracingIdwith whatever custom tracing log your backend returns

Release Statement This article is reproduced at: https://dev.to/rafaelmagalhaes/custom-fetch-with-interceptors-and-logs-in-nuxt-3-40lm?1 If there is any infringement, please contact [email protected] to delete it
Latest tutorial More>

Disclaimer: All resources provided are partly from the Internet. If there is any infringement of your copyright or other rights and interests, please explain the detailed reasons and provide proof of copyright or rights and interests and then send it to the email: [email protected] We will handle it for you as soon as possible.

Copyright© 2022 湘ICP备2022001581号-3