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 {}