Giter Club home page Giter Club logo

Comments (3)

gaspartripodiglobant avatar gaspartripodiglobant commented on July 30, 2024 1

@aashan007

It was not easy but we managed to come up with a solution so that 401 errors can be captured correctly. The solution supports simultaneous calls, which are saved until the token is refreshed.

What cannot be done from the library is to call back in the response interceptor the failed requests that have config, so it was solved by saving all the configs of the requests (don't worry, they are then deleted in the removeDataRequestsItem method) in an object in the request interceptor, to be able to be accessed in the response interceptor. A great addition to the library (which would save us having to do this step) would be to be able to access the initial config of the requests from the response interceptor.

This is the code (just use your refresh service, your REFRESH_URL and your logout method):

import fetchIntercept from 'fetch-intercept';
import { refresh, REFRESH_URL } from '...';

interface IDataRequest {
  [key: string]: Request;
}

export const CreateInterceptors = (() => {
  let instance;

  const init = () => {
    let isRefreshing = false;
    let refreshSubscribers = [];
    let dataRequests = {} as IDataRequest;

    const logoutUser = () => {
      console.log("logout method here");
    };

    const subscribeTokenRefresh = callback => {
      refreshSubscribers.push(callback);
    };

    const onRefreshed = () => {
      refreshSubscribers.map(callback => callback());
      refreshSubscribers = [];
    };

    const removeDataRequestsItem = requestKey => {
      const { [requestKey]: _omit, ...remaining } = dataRequests;
      dataRequests = remaining;
    };

    const getRelativeUrl = url => url.replace(window.location.origin, '');

    return {
      registerInterceptors: () => {
        fetchIntercept.register({
          request(url, config) {
            if (config && url.indexOf(REFRESH_URL) === -1) {
              dataRequests = {
                ...dataRequests,
                [`${getRelativeUrl(url)}_${config.method || 'GET'}`]: config,
              };
            }
            return [url, config];
          },

          response(response) {
            const requestKey = `${getRelativeUrl(response.url)}_${response.request.method}`;
            if (response.status === 401 && response.url.indexOf(REFRESH_URL) === -1) {
              if (!isRefreshing) {
                isRefreshing = true;
                refresh()
                  .then(() => {
                    isRefreshing = false;
                    onRefreshed();
                  })
                  .catch(() => logoutUser());
              }
              const retryOrigReq: any = new Promise((resolve, reject) => {
                subscribeTokenRefresh(() => {
                  fetch(response.url, {
                    ...dataRequests[requestKey],
                  })
                    .then(origReqResponse => {
                      resolve(origReqResponse);
                      removeDataRequestsItem(requestKey);
                    })
                    .catch(err => {
                      reject(err);
                    });
                });
              });
              return retryOrigReq;
            }
            removeDataRequestsItem(requestKey);
            return response;
          },
        });
      },
    };
  };

  return {
    getInstance() {
      if (!instance) {
        instance = init();
      }
      return instance;
    },
  };
})();

Then import it and call registerInterceptors:

import { CreateInterceptors } from '...';

const interceptors = CreateInterceptors.getInstance();
interceptors.registerInterceptors();

from fetch-intercept.

aashan007 avatar aashan007 commented on July 30, 2024

@gaspartripodiglobant Thanks mate

from fetch-intercept.

ruifcnunes avatar ruifcnunes commented on July 30, 2024

I solved this by applying a patch-package to fetch-intercept so that it will save the request (which already does) and the rawRequest (created by me - it will store the arguments [url, config] passed on the request intereceptor) on the response.rawRequest and error.rawRequest.

This way I always have access to the original config and original url.

from fetch-intercept.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.