Apollo-link-rest: Fehlerbehandlung behandeln

Erstellt am 2. Okt. 2018  ·  16Kommentare  ·  Quelle: apollographql/apollo-link-rest

Hallo, ich habe diese Anmelde-API, die den Anforderungshauptteil wie folgt akzeptiert:

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

Der Server gibt bei Erfolg ein Token zurück:

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

Falls die Eingabe von E-Mail oder Passwort falsch ist, wird Folgendes zurückgegeben:

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

Ich kann mich mit einem GraphQL-Schema wie diesem erfolgreich anmelden:

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

Meine Frage ist, wie kann ich im Fehlerfall eine Antwort erhalten (falsche E-Mail / falsches Passwort)? Denn gerade jetzt, wenn der Server einen Fehler zurückgibt, ist die Antwort immer null:

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

Hilfreichster Kommentar

Ich bin auch bei diesem Thema festgefahren. Gibt es einen Grund, warum nicht die vollständige 404-Antwort anstelle von null zurückgegeben wird?

Alle 16 Kommentare

Wenn Sie den Fehler 400+ nicht abfangen können, ist dieses Problem meiner Meinung nach hilfreich.
https://github.com/apollographql/apollo-link-rest/issues/151

Zu Ihrer Information: Für falsche Anmeldeinformationen sollten Sie 401 zurückgeben.
https://stackoverflow.com/questions/1959947/whats-an-eigniate-http-status-code-to-return-by-a-rest-api-service-for-a-val

Hi an alle,

Ich bin gerade darauf gestoßen und frage mich auch, wie ich mit einem 404 umgehen soll. Es löst zum Beispiel nicht das apollo-link-error aus.

Bisher denke ich darüber nach, einen benutzerdefinierten Link zur Fehlerbehandlung zu schreiben oder in der Antwort in jeder <Query /> -Komponente nach Dateninhalten zu suchen.

FWIW Ich habe den gleichen Fall, in dem ein Server beispielsweise einen 404 anstelle eines 401 zurückgibt, aber ein Serverwechsel ist derzeit leider keine Option.

Ich denke, es lohnt sich, diesen Anwendungsfall anzusprechen, da die Statuscodes für REST sehr unterschiedlich - und vielfältiger und wichtiger - sind als die von GraphQL.

Ich bin auch bei diesem Thema festgefahren. Gibt es einen Grund, warum nicht die vollständige 404-Antwort anstelle von null zurückgegeben wird?

Ich bin noch nicht auf einen Fall gestoßen, in dem es mir geholfen hat, 404 nicht als Fehler zu behandeln. Ich versuche immer wieder, einen guten Weg zu finden, um diese Tatsache zu umgehen.

Kann der Gedanke, dass 404 nicht gefunden wurde , eine Datenabfrage beschreiben, die die leere Menge erfolgreich und korrekt ergibt?

Dies könnte auch darauf hinweisen, dass die Servicebesitzer eine so wichtige Änderung vorgenommen haben, dass ein zuvor verfügbarer Endpunkt verschwunden ist.

Ich denke, der erste Fall könnte besser von 200 OK zusammen mit einer leeren oder Null-Anwendungsentität behandelt werden. Zumindest scheint es, dass diese beiden Fälle für den Kunden leicht erkennbar sein sollten, da sie sehr unterschiedlich sind.

Ja, absichtlich leere Datensätze sind etwas häufiger als man denkt? (Zumindest war ich überrascht!) Da Benutzer häufig mehrere Netzwerk- und andere Anrufe in einem einzigen Metaanruf sammeln, hat das standardmäßige Auslösen eines Fehlers auf 404 eine übergroße Auswirkung, da ein 404 alle anderen parallel abrufenden Datenabrufe beendet. Ich stimme zu, wenn nur ein REST-Aufruf pro ausgeführter GraphQL-Abfrage ausgeführt wurde, schien es mir, dass wir angesichts der offiziellen REST-Semantik einen Fehler auslösen sollten.

In der Praxis schien es besser, standardmäßig keinen Fehler zu werfen! Da Sie dies umgehen können, indem Sie einen benutzerdefinierten Abruf hinzufügen, fühlt sich dies wie "liberal in dem an, was Sie akzeptieren" an. Diese Auswahl scheint mit einem der Hauptziele von Apollo-Link-Rest übereinzustimmen: Helfen Sie Benutzern, die das Backend nicht unbedingt kontrollieren, und es gibt viele nur "meistens REST" -Server, sodass semantische Verstöße häufig sind .

@williamboman Es ist relativ einfach, Apollo-Link-Rest so zu konfigurieren, dass es auf 404s geworfen wird, wenn Sie den Parameter customFetch Ich bin nicht an meinem Computer, aber lassen Sie mich wissen, wenn Sie dabei Hilfe benötigen!

Hallo @fbartho Können Sie mir bitte beim Schreiben von customFetch helfen, um 404-Fehler zu behandeln? Gibt es ein Beispiel dafür?

@anasnain :

In Javascript würde es ungefähr so ​​aussehen:

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

(In TypeScript wäre es etwas ausführlicher)

@fbartho Danke für die schnelle Antwort. Ich kann jetzt 404 fangen.
Aber wie stelle ich sicher, dass networkError von apollo-link-error den Fehler abfängt (neuen Fehler ("404 File Not Found")), der in den benutzerdefinierten Abruf geschrieben wurde?

Ah, leider denke ich, dass es aufgrund der internen ApolloClient-Regeln (über die Funktionsweise von Links) dem Array graphQLErrors (nicht in der Eigenschaft networkError ) zugeordnet erscheint.

Es ist möglich, dass dies behoben werden kann, aber ich weiß nicht wie. - HTTPLink muss wissen, wie es geht, und ich hatte keine Gelegenheit, dies zu untersuchen. Wir haben eine Hilfsmethode in unserer (Arbeits-) Codebasis, die nur die verschachtelten Fehler entpackt. (Dies war auch für Fehler erforderlich, die von apollo-link-state für uns ausgelöst wurden, sodass dies nicht wirklich Priorität hatte.)

@fbartho Ich bekomme in diesem Fall überhaupt keinen Fehler. Daten geben null zurück. Ich habe einen Fehler anstelle von Daten erwartet, wenn wir einen Fehler auslösen. Ich bin mir nicht sicher, wie ich das implementieren soll.

@anasnain Es ist so lange her, dass ich es vergessen habe.

Sie müssen auch eine Apollo-Link-Fehlerinstanz konfigurieren. Dies ist meine Konfiguration:

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

Nach weiteren Überlegungen: Ich bin mir nicht ganz sicher, ob ich die von Ihnen beschriebene Situation verstehe.

Ist das Problem, dass Sie "404 error" in Ihrem Komponenten- / Reaktionscode nicht lesen können?

@fbartho
Szenario: Ich arbeite unter der Rest-API-Abfrage und erwarte, dass ich ein Fehlerobjekt erhalte, falls es 404-Fehlercode zurückgibt, genau wie bei anderen 4xx-Fehlern und 5xx-Fehlern. In diesem Fall ist der Fehler jedoch undefiniert und die Daten sind null.
const {Laden, Fehler, Daten} = useQuery (CLIENT_API_QUERY);

Dies ist die Apollo-Client-Instanz:

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 - Eine Sache, die mir bewusst ist, ist, dass ich nicht glaube, dass Sie ein beliebiges Objekt übergeben können, wenn Sie new Error ausführen

Ich denke auch, dass Sie eine Wartezeit verpassen, sodass die throw -Anweisung außerhalb des restLink customFetch-Aufrufs erfolgt!

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;
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen