Apollo-link-rest: apollo-link-restを使用してresponse.headersにアクセスする方法は?

作成日 2020年11月11日  ·  6コメント  ·  ソース: apollographql/apollo-link-rest

こんにちは、みんな、

apollo-link-restを使用してRESTAPIにアクセスしたいのですが、useQuery()ごとにresponse.headersアクセスすることはできません。

たとえば、ページ付けを使用したREST APIは、ヘッダーにfirst, prev, next, last情報を配置します。 どうすればそれにアクセスできますか?

ここで例を作成しました: httpssrc /

開発ツールのNetworkタブに移動し、ヘッダー付きの応答を参照しリンクには、ページネーション情報があります。 しかし、 Headersにアクセスする方法がわかりません...。

Hierが私のメインコードです。 response.headers.linkを取得する方法がわかりません...

  const queryTodos = gql`
      query Todos($page: number, $limit: number) {
        todos(_page: $page, _limit: $limit)
          @rest(type: "[Todo]", path: "/todos/?{args}") {
            userId
            id
            title
            completed
        }
     }
   `;

export const Todos = () => {
  const { data, loading, error } = useQuery(queryTodos, {
    variables: { page: 1, limit: 3 },
    fetchPolicy: "no-cache"
  });

 ...

  return (<div>...</div>)

また、stackoverflowでこの質問をしました: https

enhancement enhancement💡 feature help wanted 🛠 question❔

全てのコメント6件

@ blatoo-残念ながら、これは現在apollo-link-restには存在しない機能です。

基本的に、GraphQLはヘッダーを処理することを期待していません-ヘッダーはグラフの奥深くで返される必要があるためです。

誰かがこれを実装したい場合、応答の「本体」にシークレット/自動フィールドとして__headersを追加するのを見ることができますが、この動作を有効にするには機能フラグを追加する必要があります。 graphqlと互換性があるように、ヘッダーキーにいくつかのマングリングを行います。

const queryTodos = gql`
      query Todos($page: number, $limit: number) {
        todos(_page: $page, _limit: $limit)
          @rest(type: "[Todo]", path: "/todos/?{args}") {
+             __headers {
+                         XMyHeader
+             }
            userId
            id
            title
            completed
        }
     }
   `;

@fbarthoこの回答に感謝します。 ヘッダー情報にアクセスできれば素晴らしい機能です。 私はjson-serverを使用しています。これは、カーソルベースのページ付け情報についても、ページ付け情報をHeadersに配置します。

ちなみに、あなたのドキュメントには、 responseTansformercustomFetchオプションがあることがわかりました。 改ページ情報を取得するために彼らと何かをすることはできますか? 実際、私はたくさん試しましたが、それでも成功しませんでした...:

https://www.apollographql.com/docs/link/links/rest/#response -transforming

https://www.apollographql.com/docs/link/links/rest/#custom -fetch

残念ながら、 apollo-link-restapollo-linkのAPIに依存してGraphQLにプラグインしますが、これは、JS Headers APIを直接共有する明確な方法がないと思うことを意味します-しかし、それの非正規化バージョンが可能かもしれません。

そうは言っても、 responseTransformerまたはcustomFetchオプションを使用して、必要なものにパッチを適用することができます。

responseTransformerは、 response.headers属性を持つJS Responseオブジェクトを受け取ります。

したがって、次のように書くことができます。

responseTransformer: async (resp: Response) => {
    const body = await resp.json();
    const interestingHeaders = {};
    interestingHeaders.headerOne = resp.headers.get("headerOne"); // Pluck out the headers you want
    body.__headers = interestingHeaders
    return body;
}

ブラウザのバージョンによっては、 headers.entries()を使用して、すべてのヘッダーをheaders.get()ではなく1つのオブジェクトとして取得できる場合がありますが、現在Safari-iOSでは使用できません。

これは明らかに単純化されており、エラー処理はあなたに任されていますが、これはうまくいくと思います!

customFetchでも可能ですが、 responseTransformerが簡単だと思います。

@fbarthoうわー、これはかっこいい! 私はあなたのコードを試しました、それは動作し、私はリンクを取得しました。

ここで別の問題が発生します。クエリでbody.__headers.linkにアクセスするにはどうすればよいですか?

私のクエリコードは次のとおりです。

const queryTodos = gql`
  query Todos($page: number, $limit: number) {
    todos(_page: $page, _limit: $limit)
      @rest(type: "TodoPagination", path: "/todos/?{args}") {
      __headers {
        link
      }
      userId
      id
      title
      completed
    }
  }
`;

しかし、 __headersがnullであるもの...
コードはここにあります:私はあなたのコードをClient.tsに追加し、クエリコードはTodo.tsxます:
https://codesandbox.io/s/how-to-access-response-0mqx7?file=/src/Todos.tsx

@fbarthoこんにちは、私は3つの異なる方法を試しましたが、ついにこの問題を解決しました。 しかし、それが良い解決策であるかどうかはまだ疑問です。 ご意見をお聞かせください。

方法1:失敗しました。
最初は、 useQuery()__headersをクエリでき、複数回試行しましたが、失敗したと思います。

方法2:解決策が疑わしいため、試しませんでした
responseTransformerの応答の構造を変更し、 __headers__headersキーに入れ、todoリストをtodoキーに入れます。 しかし、それは良い解決策ではないと思います。 なぜなら、応答のすべての構造が変更されるからです。 したがって、 useQuery()すべての構造を書き直す必要があります。

方法3:成功と完全な単純
__headersをリアクティブ変数に入れました。 responseTransformer関数では、 __headersの値をリアクティブ変数に入れ、 useQuery()実行された後にクエリを実行します。 ただし、クエリごとに異なるリアクティブ変数を作成する必要があるため、まだわかりません...

@blatoo 、これは古い問題で、私自身が遭遇したばかりで、 new ApolloLinkで解決しました

const paginationLink = new ApolloLink((operation, forward) => {
  return forward(operation).map((response) => {
    const context = operation.getContext();

    const { headers } = context.restResponses[0] || null;
    // in my case i'm making a bunch of sub queries, so i'm using `[0]` to get the headers from the top level.

    if (headers) {
      const pagination = getPaginationFromHeaders(headers.get('link'));

      return { ...response, data: { ...response.data, pagination } };
    }
    return response;
  });
});

const client = new ApolloClient({
  cache: new InMemoryCache(),
  link: concat(paginationLink, restLink),
});
このページは役に立ちましたか?
0 / 5 - 0 評価