smapiot / piral

🚀 Framework for next generation web apps using micro frontends. ⭐️ Star to support our work!
https://piral.io
MIT License
1.71k stars 127 forks source link

Support User-Defined Middleware Functions in piral-fetch #645

Closed manuelroemer closed 11 months ago

manuelroemer commented 1 year ago

New Feature Proposal

For more information, see the CONTRIBUTING guide.

Description

The idea of this proposal is to allow users of piral-fetch to define arbitrary fetch middleware functions. These middleware functions would allow users to globally enhance the default behavior of piral-fetch's fetch function during the app shell setup. Middlewares are modeled similarly to other frameworks/libraries, e.g., express. For example, a custom middleware function that logs requests/responses could look like this:

// During setup:
createFetchApi({
  // New `middlewares` option which allows specifying an array of n middleware functions.
  // Middleware functions receive the same arguments as `fetch`, plus a function `next` that should
  // be invoked to call the next queued middleware and/or piral-fetch's default `fetch`.
  middlewares: [
    async (path, options, next) => {
      // Example: Log request/response information.
      console.log(`Making HTTP request to ${path}...`);
      const response = await next(path, options);
      console.log(`HTTP request finished with status code ${response.code}.`);
      return response;
    }
  ]
})

When specifiying multiple functions, they would be processed in the defined order:

createFetchApi({
  middlewares: [
    firstMiddleware,  // Processed 1st
    secondMiddleware, // Processed 2nd
    thirdMiddleware,  // Processed 3rd
  ]
})

Background

Middlewares allow additional per-project customization of the fetch function's behavior without introducing breaking changes to piral-fetch. Due to how general they are, they can be used to implement a wide variety of features, e.g., logging, caching, retrying, etc. My personal reason for making this proposal is the need for the fetch function to throw errors for non-successful response status codes for a simplified integration with the swr library. This behavior could easily be implemented globally via a middleware function like the following:

async function throwOnErrors(path, options, next) {
  const response = await next(path, options);

  if (response.code >= 400) {
    const errorMessage = `Request failed with status code ${response.code} ${response.text}.`;
    console.warn(errorMessage, response);
    throw new Error(errorMessage, { cause: response });
  }

  return response;
}

Discussion

No additional points currently - the proposal above is how I could imagine this feature to work. Please feel free to discuss any details or suggest possible improvements/problems with this!

FlorianRappl commented 1 year ago

Sounds great - you want to take it?

FlorianRappl commented 11 months ago

Any progress on this one? I move it out of the 1.4.0 milestone.

manuelroemer commented 11 months ago

Any progress on this one?

No, sorry, still busy with other work so far.