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

3

14

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

Winglet answered 14/8, 2022 at 20:7 Comment(3)
I hope it's OK to add a question as a comment. I reckon I'm trying to do what you do. Coding an authentication with JWT token without using an auth module as it seems that Nuxt 3 provide useFetch or $fetch. But I'm at a lost, have no clue to where I should start and can't find documentation, if you could share all your current configuration (specifying files name/path as well), I'll be really grateful! Thx!Instil
@Instil i guess you are building an SPA when you use JWT? if so, you should probably open a question and i can answer it there. its not very complicated or much code but it would get very confusing here. you can also drop a discord tag here and i can explain what you need to do there, your choiceWinglet
Thanks a lot for your answer @Winglet ! You're totally right and I opened a new question here: #73399110 I hope I gave you every information you need, don't hesitate to ask for more on the new thread. Thanks again! For your question I don't know if it can help but here jasonwatmore.com/post/2022/05/26/… a sort of fetch-wrapper is used. It's on a Vue project so not sure.Instil
P
6

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>
Prudy answered 16/2, 2023 at 16:6 Comment(1)
Your solution works, but it is not suitable for authentication because headers are set on the Nuxt server for $fetch. That is, about the initialisation of the application for each user, the header will be changed on the server, which will be common to all. Therefore, in the context of this question, the answer is incorrect.Demur
A
5

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.

Averil answered 11/6, 2023 at 17:4 Comment(1)
Just perfect solution.Weakness
D
3

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
    }
  })
Dittmer answered 4/7, 2023 at 19:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.