Nais_One
Nais_One

Reputation: 566

Nuxt 3: How to add default parameters and headers to $fetch

Trying to add any default parameters or headers (in this case a json web token as authentication header) to the $fetch composable so that i dont have to do

await $fetch('/api/example', {
  headers: {
    // authentication header and jwt here
  }
});

on every single request. i found a way to do this by wrapping $fetch in another composable (in this case as $api) but this removed any typings on the api response, so this is not something i want to do.

Even a simplified api.ts composable like this

export const $api = (url: string) => {
  return $fetch(url);
}

does not give me the response typings from the api result that a blank $fetch in my frontend would give me.

Can i inject default values in $fetch somehow? maybe through a module/plugin/interceptor? if not, is there a way to wrap $fetch in a composable and still keep the response typings?

i'm using nuxt3 with $fetch being ohmyfetch and i'm not using the @nuxt/auth package btw

Upvotes: 17

Views: 25377

Answers (3)

Thijs
Thijs

Reputation: 618

I've made some small changes to the answer of Riad Hachemane, because I saw that not all types were being copied to the wrapper function correctly.

import type { NitroFetchOptions, NitroFetchRequest } from 'nitropack'

const $api = async <
    DefaultT = unknown,
    DefaultR extends NitroFetchRequest = NitroFetchRequest,
    T = DefaultT,
    R extends NitroFetchRequest = DefaultR,
    O extends NitroFetchOptions<R> = NitroFetchOptions<R>
  >(
    url: R,
    options?: O
  ) => $fetch<T>(url, {
    ...options,
    headers: {
      Authorization: auth.logged ? `Bearer ${auth.accessToken}` : '',
      ...options?.headers
    }
  })

Upvotes: 3

Riad Hachemane
Riad Hachemane

Reputation: 61

You can create a composable containing a wrapper around $fetch for example under /composables/api.ts you can have:

export function $api<T>(
  request: Parameters<typeof $fetch<T>>[0],
  opts?: Parameters<typeof $fetch<T>>[1],
) {
  const auth = useAuth()

  return $fetch<T>(request, {
    ...opts,
    headers: {
      Authorization: auth.logged ? `Bearer ${auth.accessToken}` : '',
      ...opts?.headers,
    },
  })
}

Here useAuth() is a Pinia store containing auth information like logged and the access token.

Like this you can simply use $api() anywhere in the app.

Upvotes: 6

Marc Dix
Marc Dix

Reputation: 1969

Nuxt 3 is using ofetch which it exposes globally via globalThis (see here). If you want to use a preconfigured ofetch instance as $fetch instead (e.g. with headers or automatically added query params), you can override globalThis.$fetch in e.g. the <script> of your app.vue using ofetch.create and providing your default options (as documented in this section of the ofetch documentation). You can find all available options you can pass to ofetch.create in the ofetch code here and here.

Example code

app.vue

<script setup>
import { ofetch } from 'ofetch'

globalThis.$fetch = ofetch.create({ baseUrl: '', onRequest: () => {}, ... })
</script>

Upvotes: 6

Related Questions