javascriptnext.jsapollo-clientapollo-link

Apollo Client RetryLink has no headers in response


I've implemented a RetryLink into my Apollo Client as follows:

const retryLink = new RetryLink({
  attempts: (count, _, error) => {
    return count <= 5 && !!error;
  },
  delay: (count, operation) => {
    const {response: { headers }} = operation.getContext();
    // headers is always empty
    return count * 1000 * Math.random();
  }
});

The goal is to use a custom header sent by the server to adjust the delay (the server is rate limited). However, the headers field in the response is always empty. The response itself is present and looks as follows:

{
  body: (...)
  bodyUsed: true
  headers: Headers {}
  ok: false
  redirected: false
  status: 429
  statusText: ""
  type: "cors"
  url: "https://graphql.endpoint.co/"
}

If I use another link the header is there as expected. So something like this works:

const afterwareLink = new ApolloLink((operation, forward) => {
  return forward(operation).map(response => {
    const context = operation.getContext();
    const {
      response: { headers }
    } = context;

    if (headers) {
      console.log(headers.get('Retry-After'));
    }

    return response;
  });
});

The client looks like this for completeness sake:

const createApolloClient = () => {
  return new ApolloClient({
    ssrMode: typeof window === 'undefined',
    link: from([retryLink, authLink.concat(httpLink)]),
    cache: new InMemoryCache()
  });
};

Does anyone know how I could use the responses headers in a RetryLink?


Solution

  • Sometimes a night of sleep is all it takes.

    The link works just as it should. The problem was that access-control-expose-headers didn't include Retry-After. What I didn't know is that dev tools show all headers sent by the server, but scripts are only allowed to use headers included in access-control-expose-headers.

    That's the reason the header was always null.