web-dev-qa-db-ja.com

apolloクライアントのポーリングリクエストにカスタムヘッダーを追加する

使っています apollo-clientライブラリからGraphqlサーバーのデータを照会します。一部のクエリは、アポロポーリング機能を通じて5秒ごとにサーバーに送信されます。

クライアントからのポーリングで送信されたすべてのリクエストにカスタムヘッダーを追加する一般的な方法はありますか?

13
Ron Badur

2つのソリューション

それを行うには2つの方法があります。 1つはquick and easyであり、特定のクエリに対して何らかの制限付きで機能し、もう1つは一般的なソリューションですより安全で、複数のクエリで機能します。

すばやく簡単なソリューション

利点

  • 速い
  • そして...簡単

クエリを設定するとき、optionsフィールドを持つcontextフィールドを使用してクエリを設定できます。 contextの値は、ネットワークチェーンによって処理されます。 context自体はサーバーに送信されませんが、headersフィールドを追加すると、HTTP要求で使用されます。

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

ネットワークリンクミドルウェアを使用した一般的なソリューション

Apolloでは、ミドルウェアとして機能するApolloリンクを追加し、クエリ操作で設定されたcontextに基づいてリクエストにカスタムヘッダーを追加できます。

ドキュメントから:

Apollo Clientには、プラグイン可能なネットワークインターフェイスレイヤーがあり、HTTPを介してクエリを送信する方法を構成できます。

Apollo Link、ネットワークリンク、ミドルウェアの概念 の詳細をお読みください。

利点

  • ミドルウェアのロジックは、graphql操作で使用できます(条件を設定します)
  • クエリは、HTTPヘッダーを「気にする」必要も、認識する必要もありません。
  • 要求に追加するヘッダーの有無を決定する前に、さらに処理を行うことができます。
  • もっと..

コンテキストの設定

迅速かつ簡単な解決策と同じですが、今回はheadersを直接設定しません。

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

ミドルウェアの追加

Apolloには、コンテキストを設定するための特定のミドルウェアapollo-link-context(より一般的なミドルウェアでも同じことが実現できます)。

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

Httpリンクの前のどこかにあるネットワークチェーンに連結することを忘れないでください。

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

ドキュメントには別の便利な例があります: 認証にミドルウェアを使用

それだけです!サーバーからパンケーキをいくつか手に入れるべきです。お役に立てれば。

31
Tal Z

Tal Zの答えはとても良いです。しかし、Angularを使用している人のために彼がリストした2つのメソッドを実装する方法を貼り付けるだけだと思いました。

各アポロコールのヘッダーを追加する

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


  }

}

ミドルウェアにヘッダーを追加する

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