Apollo-angular: Async middleware in 1.0.0

Created on 15 Nov 2017  路  3Comments  路  Source: kamilkisiela/apollo-angular

Before, I could do:

networkInterface.use([
  {
    applyMiddleware(req, next) {
      storage.get(STORAGE_KEYS.TOKEN).then(token => {
        req.options.headers['Authorization'] = token ? `Bearer ${token}` : null;
        next();
      });
    }
  }
]);

Now, if I do:

const authMiddleware = new ApolloLink((operation, forward) => {
  return storage.get(STORAGE_KEYS.TOKEN).then(token => {
    operation.setContext({
      headers: new HttpHeaders().set('Authorization', token ? `Bearer ${token}` : null)
    });

    return forward(operation);
  });
});

I get a typescript error:

Argument of type '(operation: Operation, forward: NextLink) => Promise<Observable<any>>' is not assignable to parameter of type 'RequestHandler'.
  Type 'Promise<Observable<any>>' is not assignable to type 'Observable<any>'.
    Property 'subscribe' is missing in type 'Promise<Observable<any>>'.

How would I return a promise properly, or execute async code inside the middleware? I know I could get the token first and then apply the middleware, but I want to retrieve the token from storage for each request, i. e. inside the middleware.

Most helpful comment

Would be nice to have an example somewhere of how to do it with an Observable, but anyway I figured out another way using setContext() from apollo-link-context, which allows to be used with an async function/promise:

import { setContext } from 'apollo-link-context';
const link = this.httpLink.create({ uri: '/graphql' });

const auth = setContext(async (operation, prevContext) => {
  const token = await storage.get(STORAGE_KEYS.TOKEN);
  return {
    headers: new HttpHeaders().set('Authorization', token ? `Bearer ${token}` : null),
    // or prevContext.headers.append() if they were already set by a previous middleware
  };
});

this.apollo.create({
  link: auth.concat(link),
  cache: new InMemoryCache(),
});

Related Docs Link

All 3 comments

Instead of a Promise, return an Observable.

Now you have a Promise that returns an Observable which would cause an error.

Would be nice to have an example somewhere of how to do it with an Observable, but anyway I figured out another way using setContext() from apollo-link-context, which allows to be used with an async function/promise:

import { setContext } from 'apollo-link-context';
const link = this.httpLink.create({ uri: '/graphql' });

const auth = setContext(async (operation, prevContext) => {
  const token = await storage.get(STORAGE_KEYS.TOKEN);
  return {
    headers: new HttpHeaders().set('Authorization', token ? `Bearer ${token}` : null),
    // or prevContext.headers.append() if they were already set by a previous middleware
  };
});

this.apollo.create({
  link: auth.concat(link),
  cache: new InMemoryCache(),
});

Related Docs Link

Thanks @simonhaenisch, that was helpful

Was this page helpful?
0 / 5 - 0 ratings

Related issues

miquelferrerllompart picture miquelferrerllompart  路  7Comments

qortex picture qortex  路  4Comments

chihab picture chihab  路  4Comments

maplion picture maplion  路  4Comments

julmot picture julmot  路  3Comments