web-dev-qa-db-fra.com

Ajouter un en-tête personnalisé à la demande d'interrogation du client Apollo

J'utilise apollo-client bibliothèque pour interroger les données de mon Graphql serveur. certaines des requêtes sont envoyées au serveur toutes les 5 secondes grâce à la capacité d'interrogation apollo.

Il existe un moyen générique d'ajouter un en-tête personnalisé à toutes les demandes envoyées par l'interrogation de mon client?

13
Ron Badur

Deux solutions

Il y a deux façons de procéder. L'un est rapide et facile et fonctionnera pour une requête spécifique avec certaines limitations, et l'autre est une solution générale qui est plus sûr et peut fonctionner pour plusieurs requêtes.

Solution rapide et facile

Avantages

  • c'est rapide
  • et ... facile

Lorsque vous configurez votre requête, vous pouvez la configurer à l'aide de son champ options, qui possède un champ context. La valeur de context sera traitée par la chaîne réseau. Le context lui-même n'est pas envoyé au serveur, mais si vous lui ajoutez un champ headers, il sera utilisé dans la requête HTTP.

Exemple :

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

Solution générale utilisant un middleware Network Link

Avec Apollo, vous pouvez ajouter un lien Apollo qui agira comme un middleware et ajouter un en-tête personnalisé à la demande en fonction du context qui a été défini par votre opération de requête.

De la documentation:

Apollo Client possède une couche d'interface réseau enfichable, qui peut vous permettre de configurer la façon dont les requêtes sont envoyées via HTTP

En savoir plus sur Apollo Link, le lien réseau et les concepts de middleware .

Avantages :

  • La logique du middleware peut être utilisée par n'importe quelle opération graphql (vous définissez la condition)
  • Vos requêtes n'ont pas besoin de "prendre soin" ou de connaître les en-têtes HTTP
  • Vous pouvez effectuer davantage de traitement avant de décider si et quels en-têtes ajouter à la demande.
  • et plus..

Définition du contexte

Identique à la solution rapide et facile, mais cette fois, nous ne définissons pas directement le headers:

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

Ajout du middleware

Apollo dispose d'un middleware spécifique pour définir le contexte apollo-link-context (la même chose peut être obtenue avec un middleware plus général).

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

N'oubliez pas de le concaténer à la chaîne du réseau quelque part avant votre lien http

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

Il existe un autre exemple utile dans la documentation: en utilisant un middleware pour l'authentification .

C'est tout! Vous devriez obtenir des crêpes du serveur maintenant. J'espère que cela t'aides.

31
Tal Z

La réponse de Tal Z est très bonne. Cependant, je pensais simplement coller comment implémenter les deux méthodes qu'il a répertoriées pour ceux qui utilisent Angular.

Ajout de l'en-tête pour chaque appel apollo individuel

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
      });


  }

}

Ajout de l'en-tête dans le 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 {}
0
Diskdrive