Apollo-link-rest: Stratégie recommandée pour gérer les erreurs 404?

Créé le 6 juin 2018  ·  12Commentaires  ·  Source: apollographql/apollo-link-rest


Il est assez courant pour une API REST d'utiliser une réponse 404 pour indiquer qu'un enregistrement n'existe pas. À l'heure actuelle, lorsque cela se produit, le résultat est un networkError qui semble, par défaut, être traité comme une erreur plus fatale qu'une erreur GraphQL par la pile Apollo.

Par exemple, avec la requête:

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

Si le point de terminaison renvoie 404, il rejette avec une erreur réseau qui doit être gérée là où l'intention est susceptible d'utiliser simplement le prop de rendu error pour afficher le message d'erreur non fatal à un utilisateur. c'est-à-dire que s'il s'agissait d'une requête GraphQL au lieu de REST, cela ne serait pas classé comme une erreur réseau et serait traité de cette manière.

Ce que j'ai fait pour résoudre ce problème était d'ajouter un chèque à mon error-link qui transforme l'erreur réseau 404 en erreur GraphQL:

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

Il y a probablement encore place à l'amélioration à ce sujet, mais cela résout le problème.

Je me demandais si cela pourrait / devrait d'une manière ou d'une autre être traité dans apollo-link-rest , alors j'ai pensé que je commencerais la conversation.

enhancement💡 question❔

Tous les 12 commentaires

C'est une excellente question. - J'aimerais que ce modèle soit ajouté comme suggestion à la documentation. Je pense que c'est une classe de problèmes dont souffrent plusieurs apollo-links (apollo-link-state vient à l'esprit).

Je ne sais pas si nous sommes sûrs que c'est la bonne réponse pour tous les utilisateurs d'ApolloLink, cependant?

C'est actuellement ainsi que toutes les erreurs http sont gérées dans 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;

peut-être ajoutons-nous une fonction de correspondance de cas qui permet aux utilisateurs de dicter comment l'erreur est traitée?
Pourrait fournir des utilitaires par défaut utiles pour les cas courants tels que 404 == null

Bien que je partage la préoccupation de @fbartho selon laquelle une solution que nous introduisons pourrait ne pas convenir à tous les utilisateurs de ce lien, j'ai pensé à un cas où une erreur 404 est particulièrement nuisible. Si nous prenons cet exemple des tests:

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

et le post n'existe pas et renvoie un 404, puis la requête entière échoue sur une erreur de réseau. Bien que cela puisse être souhaité dans certains cas, il semble que le résultat devrait plutôt être:

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

Si nous voulons répondre à cela, ajouter une gestion des erreurs supplémentaire comme le suggère @paulpdaniels sera assez facile. En examinant les erreurs 4xx, je ne vois vraiment que 404 et 400/412/422 (sur les mutations) pouvant être des erreurs non fatales nécessitant un traitement spécial, soit en tant qu'erreurs GraphQL, soit en définissant le résultat sur null .

La question reste de savoir s'il est raisonnable de fournir un gestionnaire fixe pour ces erreurs ou s'il doit être laissé à error-link ou à l'application. Étant donné que plusieurs requêtes de mutation ne sont pas prises en charge (je pense?), Le seul manque actuel qui semble particulièrement pertinent est l'exemple 404 avec lequel j'ai commencé ci-dessus.

Il y a aussi la possibilité d'ajouter un gestionnaire d'erreurs à la configuration, mais il semble que cela pourrait voler des fonctionnalités à un error-link qui y appartient vraiment. Cela pourrait également rendre l'API de ce lien inutilement complexe.

@marnusw C'est une excellente réponse. Je soutiendrais un correctif qui implémente votre comportement par défaut!

142 ajoute la gestion des erreurs 404. Je pense que c'est l'élément le plus important de cette discussion.

Sur la base de nombreuses normes d' API restantes , tous les codes d'erreur doivent toujours inclure un message lisible par l'homme. Annuler ce résultat, comme cela a été fait au n ° 142, est en opposition directe avec cela.

J'ai mis en place un PR pour rétablir les 404 en tant qu'erreurs réseau normales, pour coïncider avec les bonnes pratiques de l'API REST: https://github.com/apollographql/apollo-link-rest/pull/283

@christrude bien que je ne puisse pas être en désaccord avec vous en ce qui concerne les API REST, le but de cette bibliothèque est de faire fonctionner les API REST comme GraphQL. Par conséquent, si l'approche GraphQL des ressources manquantes doit renvoyer null , alors cette bibliothèque doit convertir la convention RESTful 404 en convention de valeur de retour GraphQL null .

@christrude bien que je ne puisse pas être en désaccord avec vous en ce qui concerne les API REST, le but de cette bibliothèque est de faire fonctionner les API REST comme GraphQL. Par conséquent, si l'approche GraphQL des ressources manquantes doit renvoyer null , alors cette bibliothèque doit convertir la convention RESTful 404 en convention de valeur de retour GraphQL null .

Alors, comment GraphQL vous propose-t-il de gérer une réponse 404 dans l'interface utilisateur? Ne fais rien? Alors les demandes meurent tranquillement? C'est incroyablement mauvaise / mauvaise gestion UX / api.

Si vous interrogez un élément par ID et récupérez la valeur null, gérez-le en conséquence dans l'interface utilisateur. S'il contient des données, affichez-les.

Je suis d'accord avec @marnusw ici, nous ne pouvons pas vraiment contrôler ce que fait l'API de repos de l'utilisateur, donc la bibliothèque ne devrait pas être trop restrictive dans ce qu'elle permet. Le mappage 404 => null est une sémantique relativement intuitive qui vous permet de passer du modèle de ressource unique par requête de REST au multi-ressource par requête (du point de vue client) de GraphQL sans exploser sur les données manquantes.

Il pourrait peut-être y avoir un meilleur moyen de désactiver ce comportement, comme une version pré-packagée du transformateur de réponse ou une abstraction de la logique de traitement des demandes qui permet à l'utilisateur de contrôler entièrement la gestion de l'état http. Mais je ne pense pas que revenir au comportement précédent soit la bonne approche.

Une partie du problème de l'approche est que, dans l'abonnement aux résultats, vous ne savez pas si c'est un résultat nul parce que c'est un 404, ou s'il s'agit d'un non-retour de contenu 201 ou quelque chose de similaire. J'ai résolu ce problème dans l'après-logiciel, en vérifiant l'état et en le forçant à générer une erreur qui suppose le problème car je ne peux pas accéder au message d'erreur du serveur réel, en particulier dans mon cas, car nous utilisons la récupération personnalisée pour injecter un jeton d'authentification , et ne peut pas l'utiliser pour obtenir la réponse avant qu'apollo ne la supprime. Ma solution est une mauvaise couverture pour les autres réponses 404 dans l'application, à part le seul cas.

Cette page vous a été utile?
0 / 5 - 0 notes