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
?
Advertisement
Answer
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.