Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apollo Link response headers

I am using the latest version of Apollo Client in a simple React app and I am trying to pull out a header value from the response that is being used to show the size of the record set being returned.

I appreciate that this is not the most elegant way of providing the result set size, but that is how the API has currently been set up.

I was hoping to use the the middleware type options to do this, but when I inspect the response object I can't seem to pull out any headers.

The network trace does show that the response header is as expected so I suspect I am misunderstanding how to get at the underlying objects that I need.

I have checked the documentation, but nothing stands out as obvious hence the question here ...

like image 458
smitp33 Avatar asked Nov 22 '17 21:11

smitp33


People also ask

How do you get headers from Apollo Client?

The Apollo client does not expose the response headers to client. We can use HttpLink to send custom headers to in our requests (which we will do to authorize via 'Authorization' header), but there is no direct way to handle the response headers.

What is Apollolink?

The Apollo Link library helps you customize the flow of data between Apollo Client and your GraphQL server. You can define your client's network behavior as a chain of link objects that execute in a sequence: Apollo Client.

How do you add HTTP headers in GraphQL playground?

Unlike GraphiQL, GraphQL Playground allows you to send requests with HTTP headers, such as a token needed to authenticate a user or some other kind of authorization. Make sure to first switch the tab to “HTTP HEADERS,” and then add your headers as a JSON object. By the way, you can add more than one field.


Video Answer


2 Answers

When the backend responds, the headers should include:

Access-Control-Expose-Headers: * // or the name of your refreshToken field

Here you have the full code:

Front-end: (Apollo & React)

const httpLink = new HttpLink({ uri: URL_SERVER_GRAPHQL })

// Setup the header for the request
const middlewareAuthLink = new ApolloLink((operation, forward) => {
  const token = localStorage.getItem(AUTH_TOKEN)

  const authorizationHeader = token ? `Bearer ${token}` : null
  operation.setContext({
    headers: {
      authorization: authorizationHeader
    }
  })
  return forward(operation)
})
// After the backend responds, we take the refreshToken from headers if it exists, and save it in the cookie.
const afterwareLink = new ApolloLink((operation, forward) => {
  return forward(operation).map(response => {
    const context = operation.getContext()
    const { response: { headers } } = context

    if (headers) {
      const refreshToken = headers.get('refreshToken')
      if (refreshToken) {
        localStorage.setItem(AUTH_TOKEN, refreshToken)
      }
    }

    return response
  })
})

const client = new ApolloClient({
  link: from([middlewareAuthLink, afterwareLink, httpLink]),
  cache: new InMemoryCache()
})

In the backend (express). If we need to refresh the token (e.g: because the actual one is going to expire)

const refreshToken = getNewToken()
res.set({
  'Access-Control-Expose-Headers': 'refreshToken', // The frontEnd can read refreshToken
  refreshToken
})

Documentation from: https://www.apollographql.com/docs/react/networking/network-layer/#afterware

like image 54
Alan Avatar answered Sep 20 '22 16:09

Alan


Found the answer here: https://github.com/apollographql/apollo-client/issues/2514

Have to access it via the operation context ... interestingly the dev tools appears to show that the headers object is empty, but you can then pull named headers from it ...

const afterwareLink = new ApolloLink((operation, forward) => {
  return forward(operation).map(response => {
    const context = operation.getContext();
    const { response: { headers } } = context;
    
    if (headers) {
      const yourHeader = headers.get('yourHeader');
    }
    
    return response;
  });
});
like image 32
smitp33 Avatar answered Sep 21 '22 16:09

smitp33