Advanced

Custom client

NuxtOpenFetch uses Nuxt/Nitro plugins to provide fetch clients to the app/server

If you need to add non-serializable fetch options which can't be specified in the Nuxt config, such as signal etc, you can create custom Nuxt plugin (and Nitro plugin if you use client inside the server handler).

If you need to hook into the request/response lifecycle, you can use the provided Nuxt hooks instead.

First you need to disable the default plugin:

nuxt.config.ts
export default defineNuxtConfig({
  openFetch: {
    disableNuxtPlugin: true,
    // ...
  },
})

For example if you need to add an Abort Signal to the fetch client, you can create a Nuxt plugin like this:

plugins/openFetch.ts
export default defineNuxtPlugin({
  enforce: 'pre', // clients will be ready to use by other plugins, Pinia stores etc.
  setup(nuxtApp) {
    const clients = useRuntimeConfig().public.openFetch
    const localFetch = useRequestFetch()
    const abortController = new AbortController()

    Object.entries(clients).forEach(([name, options]) => {
      const client = createOpenFetch(localOptions => ({
        ...options,
        ...localOptions,
        signal: abortController.signal,
      }), localFetch, name, nuxtApp.hooks)

      Object.defineProperty(nuxtApp, `$${name}`, {
        configurable: true,
        enumerable: true,
        writable: true,
        value: client,
      })

      Object.defineProperty(nuxtApp.vueApp.config.globalProperties, `$${name}`, {
        configurable: true,
        enumerable: true,
        writable: true,
        value: client,
      })
    })

    return {
      provide: {
        abortController,
      },
    }
  }
})

The built-in nuxt-open-fetch plugin already installs $client methods this way, so they stay mock-friendly in Nuxt runtime tests. If you replace that plugin with a custom one, use the same descriptor pattern instead of returning the clients from provide.

Same way you can disable the Nitro plugin and provide your own fetch client:

nuxt.config.ts
export default defineNuxtConfig({
  openFetch: {
    disableNitroPlugin: true,
    // ...
  },
})
server/plugins/openFetch.ts
import { defineNitroPlugin, useRuntimeConfig } from '#imports'
import { createOpenFetch } from './fetch'

export default defineNitroPlugin((nitroApp) => {
  const clients = useRuntimeConfig().public.openFetch

  Object.entries(clients).forEach(([name, client]) => {
    nitroApp[`$${name}`] = createOpenFetch(client, nitroApp.localFetch, name, nitroApp.hooks)
  })
})

When you keep the default Nitro plugin enabled, generated clients are available with proper types on useNitroApp() inside server routes and Nitro plugins:

server/api/example.get.ts
export default defineEventHandler(async () => {
  const { $myClient } = useNitroApp()

  return $myClient('/resource')
})
Copyright © 2023 - 2026