unjs / unjs/ofetch

Allow having interceptos from both defaults and per request

Open
#319 8 comments 17 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

discussion enhancement
Dominant language
TypeScript
Stars
5.4k
Forks
195
PR merge metrics
No merged PRs in 30d

Description

Describe the feature

I need to log some data on each request/response, transform the request url (e.g. /pets/{petId} -> /pets/1) etc.
If I add onRequest to the $fetch.create and then add onRequest to the actual client:

const $myFetch = $fetch.create({
  onRequest() {
     // Log data
  }
})

$myFetch({
  onRequest() {} // logging is lost
})

handler from $fetch.create will be replaced by the handler from $myFetch.

To get around this we need to create the wrapper around $fetch:

function $myFetch(url: string, options: FetchOptions) {
  return $fetch(url, {
    ...options,
    onRequest(ctx) {
      // Log data and transform url
      // ...
      return options.onRequest?.(ctx)
    }
  })
}

What do you think about adding some sort of interceptors "merging strategy" option?

It can be done based on the idea of this PR https://github.com/unjs/ofetch/pull/353.
If we treat interceptors as an array, we can allow merging arrays from $fetch and $fetch.create. So that interceptors from $fetch and $fetch.create can be enforced to append or prepend to the resulting array of interceptors (similar to Nuxt plugins):

const $myFetch = $fetch.create({
  onRequest: [
    (ctx) => { /* Handler 1 */ }, // same as "enforce: 'default'"
    {
      enforce: 'post',
      handler: (ctx) => { /* Handler 2 */ }
    }
  ]
})

$myFetch({
  onRequest: [
    // Will be appended 
    (ctx) => { /* Handler 3 */ },
    // If you need to prepend in some scenarios
    {
      enforce: 'pre',
      handler: (ctx) => { /* Handler 4 */ }
    }
  ]
})

// Interceptors will be executed in this order:
/*
Handler 4
Handler 1
Handler 3
Handler 2
*/
Alternative Original idea
const $myFetch = $fetch.create({
  onRequest: {
    strategy: 'before', // 'overwrite' | 'before' | 'after' | 'manual', 'overwrite' by default
    handler(ctx) { ... }
  }
})

$myFetch({
  onRequest() {...}, 
})

so that interceptors from $myFetch are called after interceptors from $fetch.create.

Additional information
  • Would you be willing to help implement this feature?

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the current interceptor handling in ofetch and the behavior of $fetch.create versus per-request options. Compare the proposed array-based and strategy-based approaches, then determine the intended merge and execution order. Done means defaults and request-specific interceptors can coexist with documented ordering and passing tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api, backend-api-design
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.