Apollo-link-rest: Gestion de la réponse d'erreur

Créé le 2 oct. 2018  ·  16Commentaires  ·  Source: apollographql/apollo-link-rest

Bonjour, j'ai cette API de connexion qui prendra le corps de la requête comme:

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

Le jeton de retour du serveur en cas de succès:

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

Dans le cas où la saisie de l'email ou du mot de passe est incorrecte, elle renverra:

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

Je peux me connecter avec un schéma GraphQL comme celui-ci:

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

Ma question est de savoir comment obtenir la réponse en cas d'erreur (e-mail / mot de passe erroné)? Parce que pour le moment, si le serveur renvoie une erreur, la réponse est toujours nulle:

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

Commentaire le plus utile

Je suis également coincé sur cette question. Y a-t-il une raison pour ne pas renvoyer la réponse 404 complète au lieu de null?

Tous les 16 commentaires

Si vous ne pouvez pas attraper l'erreur 400+, je pense que ce problème sera utile.
https://github.com/apollographql/apollo-link-rest/issues/151

FYI: pour les informations d'identification erronées, vous devez renvoyer 401.
https://stackoverflow.com/questions/1959947/whats-an-appropriate-http-status-code-to-return-by-a-rest-api-service-for-a-val

Salut tout le monde,

Je viens de rencontrer ceci et je me demande aussi quelle est la manière recommandée de gérer un 404. Cela ne déclenche pas le apollo-link-error par exemple.

Jusqu'à présent, je pense à écrire un lien de gestionnaire d'erreur personnalisé ou à vérifier le contenu des données dans la réponse de chaque composant <Query /> .

FWIW J'ai le même cas où un serveur renvoie un 404 au lieu d'un 401 par exemple, mais changer le serveur n'est malheureusement pas une option à ce stade.

Je pense qu'il vaudrait la peine de traiter ce cas d'utilisation car les codes d'état pour REST sont très différents - et plus variés et importants - que ceux de GraphQL.

Je suis également coincé sur cette question. Y a-t-il une raison pour ne pas renvoyer la réponse 404 complète au lieu de null?

Je n'ai pas encore rencontré de cas où le fait de ne pas traiter 404 comme une erreur m'a aidé, je continue d'essayer de trouver un bon moyen de contourner ce fait.

Est-ce que le fait de penser que 404 Not found pourrait décrire une requête de données qui aboutit correctement à l'ensemble vide?

Cela pourrait également signaler que les propriétaires de services ont effectué une telle modification décisive qu'un point d'extrémité précédemment disponible a disparu.

Je pense que le premier cas pourrait être mieux géré par 200 OK avec une entité d'application vide ou nulle. Au moins, il semble que ces deux cas devraient être facilement discernables par le client, car ils sont très différents.

Oui, les ensembles de données intentionnellement vides sont un peu plus courants qu'on ne le pense? (Au moins j'ai été surpris!) Étant donné que les utilisateurs collectent souvent plusieurs appels réseau et autres en un seul méta-appel, le fait de lancer par défaut une erreur sur 404 a un impact démesuré, car un 404 mettrait fin à toutes les autres récupérations de données qui se produisent en parallèle. Je suis d'accord s'il n'y avait qu'un seul appel REST par requête GraphQL exécutée, il m'a semblé que nous devrions lancer une erreur étant donné la sémantique officielle REST.

En pratique, ne pas lancer d'erreur par défaut semblait mieux! Puisque vous pouvez contourner ce problème en ajoutant une récupération personnalisée, cela ressemble à «soyez libéral dans ce que vous acceptez»; ce choix semblait correspondre à l'un des objectifs clés d'Apollo-link-rest: aider les utilisateurs qui ne contrôlent pas nécessairement le backend, et il existe de nombreux serveurs uniquement «principalement REST», les violations sémantiques sont donc courantes .

@williamboman, il est relativement simple de configurer Apollo-link-rest pour lancer des 404 si vous utilisez le paramètre customFetch Je ne suis pas sur mon ordinateur, mais faites-moi savoir si vous avez besoin d'aide pour cela!

Salut @fbartho Pouvez-vous m'aider à écrire customFetch pour gérer les erreurs 404? Y a-t-il un exemple là-dessus?

@anasnain :

En javascript, cela ressemblerait à ceci:

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

(Dans TypeScript, ce serait un peu plus détaillé)

@fbartho Merci pour la réponse rapide. Je suis en mesure d'attraper 404 maintenant.
Mais comment puis-je m'assurer que networkError de apollo-link-error intercepte l'erreur (throw new Error ("404 File Not Found")) écrite à l'intérieur de la récupération personnalisée?

Ah, malheureusement, je pense qu'il apparaîtra attaché au tableau graphQLErrors (pas sur la propriété networkError ) en raison des règles internes d'ApolloClient (sur le fonctionnement des liens).

Il est possible que cela soit réparable, mais je ne sais pas comment. - HTTPLink doit savoir comment faire, et je n'ai pas eu la chance d'enquêter. Nous avons une méthode d'assistance dans notre base de code (de travail) qui décompresse simplement les erreurs imbriquées. (Cela était également nécessaire pour les erreurs générées à partir de apollo-link-state pour nous, donc ce n'était pas vraiment une priorité)

@fbartho Je n'obtiens aucune erreur dans ce cas. les données renvoient null. s'attendait à une erreur au lieu de données si nous lançons une erreur. Je ne sais pas comment mettre en œuvre cela.

@anasnain Cela fait si longtemps que je ne l'ai pas installé, j'ai oublié.

Vous devez également configurer une instance apollo-link-error, voici ma configuration:

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

Après réflexion: je ne suis pas tout à fait sûr de comprendre la situation que vous décrivez.

Le problème est-il que vous ne pouvez pas lire "erreur 404" dans votre code composant / réaction?

@fbartho
Scénario: je cours sous la requête d'API de repos et je m'attends à ce que je reçoive un objet d'erreur au cas où il renvoie le code d'erreur 404, tout comme dans le cas d'autres erreurs 4xx et 5xx. mais dans ce cas, l'erreur n'est pas définie et les données sont nulles.
const {chargement, erreur, données} = useQuery (CLIENT_API_QUERY);

Voici l'instance client 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 - une chose dont je suis consciente est que je ne pense pas que vous puissiez passer un objet arbitraire en faisant new Error

De plus, je pense que vous manquez une attente, donc l'instruction throw se produit en dehors de l'appel 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;
Cette page vous a été utile?
0 / 5 - 0 notes