Apollo-link-rest: 404エラーを処理するための推奨戦略?

作成日 2018年06月06日  ·  12コメント  ·  ソース: apollographql/apollo-link-rest


REST APIが404応答を使用して、レコードが存在しないことを示すことは非常に一般的です。 現在、これが発生すると、結果はnetworkErrorになります。これは、デフォルトでは、ApolloスタックによるGraphQLエラーよりも致命的なエラーとして扱われるようです。

たとえば、次のクエリを使用します。

query BookQuery($slug: ID!) {
  book(slug: $slug) @rest(type: "Book", path: "book/:slug") {
    name
    author
  }
}

エンドポイントが404を返す場合、ネットワークエラーで拒否されます。ネットワークエラーは、意図的にerrorレンダープロップを使用して致命的でないエラーメッセージをユーザーに表示する可能性が高い場合に処理する必要があります。 つまり、これがRESTではなくGraphQLクエリである場合、これはネットワークエラーとして分類されず、このように処理されます。

これを修正するために私がしたことは、404ネットワークエラーをGraphQLエラーに変換するチェックをカスタムerror-linkに追加すること

forward(operation).subscribe({
  next: result => {...},
  error: networkError => {
    if (networkError.statusCode === 404) {
      return observer.next({errors: [networkError]});
    }
    //...
    observer.error(networkError);
  },
  complete: observer.complete.bind(observer),
});

これにはまだ改善の余地があると思われますが、問題は解決します。

これはどういうわけかapollo-link-restで対処できるのではないかと思っていたので、会話を始めることにしました。

enhancement💡 question❔

全てのコメント12件

それは素晴らしい質問です。 -このパターンをドキュメントへの提案として追加したいと思います。 複数のアポロリンクが苦しんでいるのは一種の問題だと思います(アポロリンクステートが思い浮かびます)。

しかし、これがApolloLinkのすべてのユーザーにとって正しい答えであると確信しているのかわかりません。

これは現在、すべてのhttpエラーがapollo-link-restで処理される方法です。

        if (res.status >= 300) {
          // Throw a JSError, that will be available under the
          // "Network error" category in apollo-link-error
          let parsed: any;
          try {
            parsed = await res.json();
          } catch (error) {
            // its not json
            parsed = await res.text();
          }
          rethrowServerSideError(
            res,
            parsed,
            `Response not successful: Received status code ${res.status}`,
          );
        }
        return res;

おそらく、エラーの処理方法をユーザーが指示できるケースマッチング関数を追加しますか?
404 == nullような一般的なケースに役立つデフォルトのユーティリティを提供できます

私たちが紹介する解決策がこのリンクのすべてのユーザーにとって適切ではないかもしれないという@fbarthoの懸念を共有しますが、404エラーが特に有害である1つのケースを考えました。 テストからこの例をとると、次のようになります。

query postAndTags {
  post @rest(type: "Post", path: "/post/1") {
    id
    title
  }
  tags @rest(type: "[Tag]", path: "/tags") {
    name
  }
}

postが存在せず、404を返すと、ネットワークエラーでクエリ全体が失敗します。 場合によってはそれが望まれることもありますが、結果はむしろ次のようになります。

const data = {
  post: null,
  tags: [{ name: 'apollo' }, { name: 'graphql' }],
}

これに対応したい場合は、 @ paulpdanielsが示唆するようにエラー処理を追加するのは非常に簡単です。 4xxエラーを見ると、実際には404と400/412/422(ミューテーション)のみが、GraphQLエラーとして、または結果をnull設定するなど、特別な処理を必要とする致命的でないエラーである可能性があります。

これらのエラーに固定ハンドラーを提供することが合理的かどうか、またはerror-linkまたはアプリケーションに任せる必要があるかどうかという疑問が残ります。 複数のミューテーションクエリはサポートされていないので(私は思いますか?)、特に関連すると思われる現在の欠点は、上記で始めた404の例だけです。

構成にエラーハンドラーを追加するオプションもありますが、実際にそこに属しているerror-linkから機能を盗む可能性があるようです。 また、このリンクのAPIが不必要に複雑になる可能性もあります。

@marnuswそれは素晴らしい反応です。 デフォルトであなたの振る舞いを実装する修正をサポートします!

142は404エラー処理を追加します。 それがこの議論の中で最も重要なことだと思います。

多くのRESTAPI標準に基づいて、すべてのエラーコードには常に人間が読めるメッセージを含める必要があります。 #142で行われたように、その結​​果を無効にすることは、それに正反対です。

良いRESTAPIプラクティスと一致するように、404を通常のネットワークエラーとして復元するためのPRを作成しました: https

@christrude REST APIに関する限り、私はあなたに反対することはできませんが、このライブラリの目的は、RESTAPIをGraphQLのように機能させることです。 したがって、不足しているリソースに対するGraphQLアプローチがnullを返すことである場合、このライブラリはRESTful404規則をGraphQL null戻り値規則に変換する必要があります。

@christrude REST APIに関する限り、私はあなたに反対することはできませんが、このライブラリの目的は、RESTAPIをGraphQLのように機能させることです。 したがって、不足しているリソースに対するGraphQLアプローチがnullを返すことである場合、このライブラリはRESTful404規則をGraphQL null戻り値規則に変換する必要があります。

では、GraphQLはUIで404応答を処理することをどのように提案しますか? 何もしない? それで、要求はただ静かに死ぬのですか? それは信じられないほど悪い/貧弱なUX / API管理です。

IDでアイテムをクエリし、nullが返される場合は、UIでそれに応じて処理します。 データが含まれている場合は表示します。

私はここで@marnuswに同意します。ユーザーの残りのAPIが何をするかを実際に制御することはできないので、ライブラリが許可するものを過度に制限するべきではありません。 404 => nullマッピングは比較的直感的なセマンティクスであり、RESTのリクエストごとの単一リソースモデルからGraphQLのリクエストごとのマルチリソース(クライアントの観点から)に、不足しているデータを爆破することなく移動できます。

おそらく、この動作をオプトアウトするためのより良い方法があるかもしれません。たとえば、事前にパッケージ化されたバージョンの応答トランスフォーマーや、ユーザーがhttpステータス処理を完全に制御できるようにする要求処理ロジックの抽象化などです。 しかし、以前の動作に戻すことは正しいアプローチではないと思います。

このアプローチの問題の一部は、結果サブスクリプションで、404が原因で結果がnullであるかどうか、またはコンテンツが返されない201などであるかどうかがわからないことです。 私はこれをアフターウェアで修正し、ステータスをチェックして、実際のサーバーエラーメッセージにアクセスできないため、特にカスタムフェッチを使用して認証トークンを挿入するため、問題を想定したエラーをスローするように強制します、およびapolloが削除する前に応答を取得するためにそれを使用することはできません。 私の解決策は、1つのケースを除いて、アプリ全体の他の404応答の悪いブランケットです。

このページは役に立ちましたか?
0 / 5 - 0 評価