GithubHelp home page GithubHelp logo

Comments (5)

twelve17 avatar twelve17 commented on May 7, 2024 1

Another use case is for JWT-refresh. The order of operation is basically:

  1. request 1 gets a 401. It is implied, but not known, that it is because of an expired JWT.
  2. a separate request is made to another resource to refresh the JWT
  3. request 1 is retried. If it gets a 401 again, then it should be treated as a fatal error, as now it is no longer implied to be caused by an expired JWT.

The implementations I've seen (outside of Apollo) require keeping some state:

  • a boolean "has the JWT refresh request been made?", so that the retry does not get stuck in a loop in case some other issue is causing a 401 that is unrelated to the JWT.
  • a boolean "is this the refresh JWT request itself?", so that the retry logic is not used on that request
  • at the time of the response of request 1, a reference to the original request would be needed, so it could be retried.

Just my 2 cents. :)

(I eventually got here via this discussion.)

from apollo-fetch.

evans avatar evans commented on May 7, 2024

I should have a better answer for you in a couple of hours. The current reasons are simplicity of the middleware and aftwerware in their implementations and clarity of the order of their application. Your suggestion is certainly worth investigating. Are there any use cases you can think of that might need this sort of access to request and response?

While we are thinking about the middleware/afterware structure, another plan to look at is the specification for apollo-link, especially "Composing Links into a chain". Links are designed to modify GraphQL control flow with an HttpLink(calls ApolloFetch) or other transport link at the end of the chain. apollo-fetch deals with everything fetch and http specific. I'm curious to hear your thoughts on apollo-link and the interplay between link and fetch.

from apollo-fetch.

inxilpro avatar inxilpro commented on May 7, 2024

I guess I just think adding the concept of "afterware" just means that people have to deal with two concepts and the library has to handle two stacks/loops/etc. When everything is implemented as middleware it keeps it simple, and it allows for middleware that modifies the request and response. So in your auth example:

function makeAuthMiddleware(auth) {
  return (req, opts, next) => {
    opts.headers = opts.headers || {};
    opts.headers.authorization = auth.createAuthorizationToken();
    
    const res = next(req, opts);
    if (401 === res.status) {
      auth.logout();
    }
    return res;
  };
}

Using a pipeline is pretty straightforward:

function runMiddleware(middleware, req = {}, opts = {}) {
  const final = (req, opts) => {
    // FIXME:
    return `build body from ${JSON.stringify(req)} and do fetch() with ${JSON.stringify(opts)}`;
  };
  
  if (0 === middleware.length) {
    return final(req, opts);
  }
  
  if (1 === middleware.length) {
    return middleware[0](req, opts, final);
  }
  
  const pipeline = middleware.reduce((next, current) => {
    return (req, opts) => current(req, opts, next);
  }, final);
  
  return pipeline(req, opts);
}

Demo:

const req = { foo: 'bar' };
const opts = { headers: { 'x-bar': 'baz'}};
const middleware = [
  (req, opts, next) => {
    opts.headers = opts.headers || {};
    opts.headers.authorization = 'auth header';
    
    const res = next(req, opts);
    return `Check auth, then ${res}`;
  },
  (req, opts, next) => next(req, opts).replace(/"/g, ''),
];

console.log(runMiddleware(middleware, req, opts));

// Check auth, then build body from {foo:bar} and do fetch() with {headers:{x-bar:baz,authorization:auth header}}

I think the apollo-link spec looks interesting in a lot of ways, but it seems to me that apollo-fetch should be as simple as possible.

from apollo-fetch.

inxilpro avatar inxilpro commented on May 7, 2024

There are lots of cases where middleware would want to modify both the request and response. Another common one would be logging:

function log(req, opts, next) => {
  console.log('Requesting:', req, opts);
  const res = next(req, opts);
  console.log('Result:', res);
  return res;
};

from apollo-fetch.

evans avatar evans commented on May 7, 2024

@inxilpro Thank you for the suggestions! Right now, we are going to stick with the current interface for middleware and afterware, so that we get backwards compatibility with Apollo Client's middleware and afterware. Are you interested in contributing the functionality for middleware's next to return the fetch result from the afterware?

The proposed order of execution would be:

apolloFetch.use(m1).use(m2).useAfter(a1).useAfter(a2)

m1 > m2 > fetch > a1 > a2 > m2 > m1

Let me know what you think! This could be a good migration path toward deprecating afterware in apollo-fetch

It also sound like you had some ideas on how to apply the middleware/afterware more efficiently. If you are interested in that more, this code handles the ware application.

from apollo-fetch.

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.