Add custom header to apollo client polling request

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.


Tal Z's answer is very good. However, I thought I'd just paste how to implement the two methods he's listed for those using Angular.

Adding the header for each individual apollo call

import { Component, OnInit } from '@angular/core';
import { LocalStorageService } from 'angular-2-local-storage';
import { Apollo } from 'apollo-angular';
import gql from 'graphql-tag';
import { Pineapples, Pineapple } from './models/pineapples';

export class AppComponent {

  constructor(private apollo: Apollo,
    private localStorageService: LocalStorageService) {
  }

  callGraphQLQuery() {

    const token = this.localStorageService.get('loginToken');
    this.apollo
      .watchQuery<Pineapples>({

        query: gql`
        {
          pineapples{
            id
            name
          }
        }
      `, 
       context: {
           headers: new HttpHeaders().set("Authorization", "Bearer " + token),
         }
      })
      .valueChanges.subscribe(result => {
        // handle results here
      });


  }

}

Adding the header in the middleware

const uri = 'https://localhost:5001/graphql'; 

export function createApollo(httpLink: HttpLink, localStorage: LocalStorageService) {

  const http = httpLink.create({ uri });

  const authLink = new ApolloLink((operation, forward) => {
    // Get the authentication token from local storage if it exists
    const token = localStorage.get('loginToken');

    // Use the setContext method to set the HTTP headers.
    operation.setContext({
      headers: {
        'Authorization': token ? `Bearer ${token}` : ''
      }
    });

    // Call the next link in the middleware chain.
    return forward(operation);
  });

  return {
    link: authLink.concat(http),
    cache: new InMemoryCache()
  };
}

@NgModule({
  exports: [ApolloModule, HttpLinkModule],
  providers: [
    {
      provide: APOLLO_OPTIONS,
      useFactory: createApollo,
      deps: [HttpLink, LocalStorageService],
    },
  ],
})
export class GraphQLModule {}