Apollo-link-rest: エラー応答の処理

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

こんにちは、私はこのサインインAPIを持っています。これはリクエストの本文を次のように受け取ります。

{
    "authentications": {
        "emailAddress": "[email protected]",
        "password": "11111111"
    }
}

成功した場合、サーバーはトークンを返します。

{
    "authentications": {
        "token": "eyJhbGoiU3RvcmUifV0sImNyZWF0ZWRBdCI6IjIwMTgtMDktMTZUMTg6NTA6NTYuNT"
    }
}

電子メールまたはパスワードの入力が正しくない場合は、次のように返されます。

{
    "message": "Cannot find document for class 'User'. searched with parameters: '{\"emailAddress\":\"[email protected]\"}'",
    "errorCode": 1103,
    "status": 404
}

次のようなGraphQLスキーマで正常にサインインできます。

gql`
  fragment Authentications on any {
    emailAddress: String
    password: String
  }

  fragment AuthInput on REST {
    authentications {
      Authentications
    }
  }

  mutation signIn($input: AuthInput!) {
    authPayload(input: $input) 
      @rest(type: "AuthPayload", path: "/api/v1/authentications", endpoint:"UsersService", method:"POST") {
      authentications @type(name:"Auth"){
        token
      }
    }
  }
`;

私の質問は、エラー(間違った電子メール/パスワード)の場合にどのように応答を得ることができますか? 現在、サーバーがエラーを返した場合、応答は常にnullになるためです。

Object {
    "data": Object {
        "authPayload": null,
    },
    "errors": undefined,
}
help wanted 🛠 question❔

最も参考になるコメント

私もこの問題にこだわっています。 nullではなく完全な404応答を返さない理由はありますか?

全てのコメント16件

エラー400+を​​キャッチできない場合は、この問題が役立つと思います。
https://github.com/apollographql/apollo-link-rest/issues/151

参考:間違ったクレデンシャルの場合は、401を返す必要があります。
https://stackoverflow.com/questions/1959947/whats-an-appropriate-http-status-code-to-return-by-a-rest-api-service-for-a-val

こんにちは、みんな、

私はちょうどこれに遭遇しました、そして私も404を処理するための推奨される方法が何であるか疑問に思っています。それは例えばapollo-link-errorをトリガーしません。

これまでのところ、カスタムエラーハンドラリンクを作成するか、各<Query />コンポーネントの応答のデータコンテンツを確認することを考えています。

FWIWたとえば、サーバーが401ではなく404を返すという同じケースがありますが、残念ながら、現時点ではサーバーを変更することはできません。

RESTのステータスコードはGraphQLのものとは非常に異なり、より多様で重要であるため、このユースケースに対処する価値があると思います。

私もこの問題にこだわっています。 nullではなく完全な404応答を返さない理由はありますか?

404をエラーとして扱わないことが役に立ったというケースにはまだ遭遇していません。私は、その事実を回避するための良い方法を見つけようと努力を続けています。

404 Not foundは、空のセットを正常に生成するデータクエリを記述できると考えていますか?

また、サービスオーナーが、以前に利用可能だったエンドポイントが消えるほどの重大な変更を加えたことを示す場合もあります。

最初のケースは、空またはnullのアプリケーションエンティティとともに200OKで処理する方がよいと思います。 少なくとも、これら2つのケースは非常に異なるため、クライアントはすぐに識別できるはずです。

はい、意図的に空のデータセットは、想像以上に一般的ですか? (少なくとも私は驚きました!)ユーザーは多くの場合、複数のネットワークおよびその他の呼び出しを1つのメタ呼び出しに収集しているため、デフォルトで404にエラーをスローすると、並行して発生する他のすべてのデータフェッチが終了するため、大きな影響があります。 実行されたGraphQLクエリごとにREST呼び出しが1つしかない場合は同意しますが、公式のRESTセマンティクスを考えるとエラーをスローする必要があるように思われました。

実際には、デフォルトでエラーをスローしない方が良いように見えました! カスタムフェッチを追加することでこれを回避できるため、これは「受け入れるものに寛大である」ように感じます。 この選択は、Apollo-link-restの主要な目的の1つと一致しているように感じました。バックエンドを必ずしも制御する必要のないユーザーを支援し、「ほとんどREST」サーバーしかないため、セマンティック違反が一般的です。 。

@williamboman customFetchパラメーターを使用する場合、404をスローするようにApollo-link-restを構成するのは比較的簡単です。私はコンピューターを使用していませんが、サポートが必要な場合はお知らせください。

こんにちは@ fbartho404エラーを処理するためにcustomFetchを書くのを手伝ってくれませんか? 例はありますか?

@anasnain

javascriptでは、次のようになります。

export async function customFetch(requestInfo, init) {
  const response = await fetch(requestInfo, init);
  if (response.status === 404) {
    throw new Error("404 File Not Found"); // Customize this however you like!
  }
  return response;
}

(TypeScriptではもう少し冗長になります)

@fbartho迅速な対応に感謝します。 私は今404を捕まえることができます。
しかし、apollo-link-errorのnetworkErrorがカスタムフェッチ内に書き込まれたエラー(throw new Error( "404 File Not Found"))を確実にキャッチするにはどうすればよいですか?

ああ、残念ながら、ApolloClientの内部ルール(リンクの動作について)により、( networkErrorプロパティではなく) graphQLErrors配列にアタッチされているように見えると思います。

これは修正可能である可能性がありますが、方法がわかりません。 --HTTPLinkはそれを行う方法を知っている必要があり、私は調査する機会がありませんでした。 (作業)コードベースには、ネストされたエラーを解凍するだけのヘルパーメソッドがあります。 (これは、 apollo-link-stateからスローされたエラーにも必要だったため、実際には優先事項ではありませんでした)

@fbarthoこの場合、エラーはまったく発生しません。 データがnullを返しています。 エラーをスローしている場合、データではなくエラーを予期していました。 これを実装する方法がわからない。

@anasnain設定してから久しぶり、忘れてしまいました。

また、apollo-link-errorインスタンスを構成する必要があります。これが私の構成です。

const attachGQLErrorsToNetworkError = (
    graphQLErrors: readonly GraphQLError[],
    networkError: Error,
): void => {
    (networkError as any).tr_graphQLErrors = graphQLErrors;
    return;
};

/** Set behavior when errors occur and handle our own TR errors */
export const apolloErrorLink = onError((errorResponse: ErrorResponse) => {
    const {
        graphQLErrors = [],
        networkError,
    }: {
        graphQLErrors?: readonly GraphQLError[];
        networkError?: Error;
    } = errorResponse;

    /**
     * Our error parsing (function recursiveGQLErrorsFromNetworkError) rely
     * on attaching the following graphql errors.
     * Let's make sure to not attach anything `wrong` (ie: null, empty, ...)
     */
    const hasGraphQLErrors: boolean =
        graphQLErrors != null &&
        Array.isArray(graphQLErrors) &&
        graphQLErrors.length > 0;

    if (networkError && hasGraphQLErrors) {
        /*
         * graphQLErrors are not being passed through the chain of links,
         * but network errors are attaching the graphQLErrors to networkError
         * to be able to access them in a component
         */
        attachGQLErrorsToNetworkError(graphQLErrors, networkError);
    }
});

さらに熟考した後:あなたが説明している状況を私が理解しているのか完全にはわかりません。

コンポーネント/ Reactコードで「404エラー」を読み取れないという問題はありますか?

@fbartho
シナリオ:残りのAPIqueryの下で実行していますが、他の4xxエラーや5xxエラーの場合と同じように、404エラーコードが返される場合はエラーオブジェクトを取得する必要があります。 ただし、この場合、エラーは未定義であり、データはnullです。
const {loading、error、data} = useQuery(CLIENT_API_QUERY);

これはApolloクライアントインスタンスです。

async function customFetch(requestInfo, init) {
    const response = await fetch(requestInfo, init);
    if (response.status === 404) {
        response.json().then((errorResponse) => {
          throw new Error(errorResponse);
        });
    }
    return response;
  }

const errorLink = onError(({ operation, response, graphQLErrors, networkError }) => {
    if (graphQLErrors) {
      graphQLErrors.forEach(({ message, path }) =>
           console.log(`[GraphQL error]: Message: ${message}, Path: ${path}`),
      );
    }
    if (networkError) {
        console.log(`[Network error ${operation.operationName}]: ${networkError.message}`);
    }
  });

const restLink = new RestLink({
    uri: 'https://run.mocky.io/v3/df72bacd-39cb-476d-bfda-06d7f5e9d77d',
    customFetch: (requestInfo, init) => customFetch(requestInfo, init)
});

const apolloClient = new ApolloClient({
    link: ApolloLink.from([errorLink, restLink]),
    new InMemoryCache(),
  });
export default apolloClient;

@ anasnain-私が知っていることの1つは、 new Error実行するときに任意のオブジェクトを渡すことができないと思うことです。

また、あなたは待ちを逃していると思うので、 throwステートメントはrestLink customFetch呼び出しの外で起こっています!

const err = new Error("404 Error");
try {
  err.responseJson = await response.json(); // This await crucial to get the error in the right spot!
} catch (parsingError) {
  // figure out what you want to do with parsingError?
}
throw err;
このページは役に立ちましたか?
0 / 5 - 0 評価