Search code examples
javascriptgraphqlapolloapollo-clientgraphql-js

Add custom header to apollo client polling request


I am using the apollo-client library to query data from my Graphql server. Some of the queries are sent to the server every 5 seconds through apollo polling ability.

Is there a generic way to add a custom header to all requests that are sent by my polling client?


Solution

  • Two Solutions

    There are two ways to do that. One is quick and easy and will work for a specific query with some limitation, and the other is a general solution that is safer and can work for multiple queries.

    Quick and Easy Solution

    Advantages

    • it's quick
    • and... easy

    When you configure your query you can configure it using its options field, that has a context field. The value of context will be processed by the network chain. The context itself is not sent to the server, but if you add a headers field to it, it will be used in the HTTP request.

    Example:

    const someQuery = graphql(gql`query { ... }`, {
      options: { 
        context: { 
          headers: { 
            "x-custom-header": "pancakes"  // this header will reach the server
          } 
        },
        // ... other options  
      }
    })
    

    General Solution using a Network Link middleware

    With Apollo you can add an Apollo Link that will act as a middleware and add a custom header to the request based on the context that was set by your query operation.

    From the docs:

    Apollo Client has a pluggable network interface layer, which can let you configure how queries are sent over HTTP

    Read more about Apollo Link, the network link and Middleware concepts.

    Advantages:

    • The middleware's logic can be used by any graphql operation (you set the condition)
    • Your queries don't need to "care" or know about HTTP headers
    • You can do more processing before deciding if and what headers to add to the request.
    • and more..

    Setting the context

    Same as the quick and easy solution, only this time we don't set the headers directly:

     {
       options: { 
         context: { 
           canHazPancakes: true //this will not reach the server
         }
       }
     }
    

    Adding the middleware

    Apollo has a specific middleware for setting the context apollo-link-context (the same can be achieved with a more general middleware).

    import {setContext} from 'apollo-link-context'
    
    //... 
    
    const pancakesLink = setContext((operation, previousContext) => { 
      const { headers, canHazPancakes } = previousContext
      if (!canHazPancakes) { 
        return previousContext
      }
    
      return {
        ...previousContext,
        headers: {    
          ...headers,
          "x-with-pancakes": "yes" //your custom header
        }
      }
    })
    

    Don't forget to concat it to the network chain somewhere before your http link

    const client = new ApolloClient({
      // ...
      link: ApolloLink.from([
        pancakesLink,
        <yourHttpLink>
      ])
    })
    

    There is another useful example in the docs: using a middleware for authentication.

    That's it! You should get some pancakes from the server now. Hope this helps.