REST-API-Fehler geben bewährte Methoden zurück [geschlossen]

623

Ich suche nach Anleitungen zu bewährten Methoden, wenn es darum geht, Fehler von einer REST-API zurückzugeben. Ich arbeite an einer neuen API, damit ich jetzt in jede Richtung gehen kann. Mein Inhaltstyp ist derzeit XML, aber ich plane, JSON in Zukunft zu unterstützen.

Ich füge jetzt einige Fehlerfälle hinzu, z. B. versucht ein Client, eine neue Ressource hinzuzufügen, hat jedoch sein Speicherkontingent überschritten. Ich behandle bereits bestimmte Fehlerfälle mit HTTP-Statuscodes (401 für die Authentifizierung, 403 für die Autorisierung und 404 für einfache URIs für fehlerhafte Anforderungen). Ich habe mir die gesegneten HTTP-Fehlercodes angesehen, aber keiner der Bereiche 400-417 scheint richtig zu sein, um anwendungsspezifische Fehler zu melden. Zuerst war ich versucht, meinen Anwendungsfehler mit 200 OK und einer bestimmten XML-Nutzlast zurückzugeben (dh zahlen Sie uns mehr und Sie erhalten den Speicher, den Sie benötigen!), Aber ich habe aufgehört, darüber nachzudenken, und es scheint zu seifen (/ Achselzucken vor Entsetzen). Außerdem scheint es, als würde ich die Fehlerantworten in verschiedene Fälle aufteilen, da einige vom http-Statuscode und andere vom Inhalt abhängen.

Was sind die Empfehlungen der Branche? Gute Praktiken (bitte erklären Sie warum!) Und aus Sicht eines Client-POV, welche Art der Fehlerbehandlung in der REST-API erleichtert dem Client-Code das Leben?

Remus Rusanu
quelle
7
Nur zur Klarstellung: Ich bin nicht so sehr daran interessiert, welchen bestimmten HTTP-Statuscode zurückgegeben werden soll, sondern ob es eine gute REST-Praxis ist, Nutzdatenfehler mit HTTP-Statuscodes zu kombinieren, oder ob es besser ist, sich ausschließlich auf die Nutzdaten zu verlassen.
Remus Rusanu
3
Das REST API Design Handbook behandelt dieses Thema recht gut.
Remus Rusanu
12
Die Frage fragt nicht nach einer Meinung, sondern nach Leitlinien / Empfehlungen und sollte erneut geöffnet und als Referenz verwendet werden. Was war der Grund, um 2016 die Frage zu schließen, die im Jahr 2009 erstellt wurde, hat 400+ Stimmen und keine der vorhandenen Antworten basierend auf Meinungen
Michael Freidgeim
4
Die meisten haben dies nicht erwähnt, aber die Verwendung der HTTP-Fehlercodes kann zu Problemen hinsichtlich der Hauptursache eines Problems führen. HTTP ist das Transportprotokoll und ein 404 sollte anzeigen, dass ein Problem mit der URLon-Transportebene aufgetreten ist (z. B. falscher Pfad). Wenn die Anwendung ein Dataset anhand ihrer ID nicht finden kann, handelt es sich um einen Fehler auf Anwendungsebene (kein Fehler auf Transportebene), und ein 404, wie von Benutzern eines erholsamen http-Statuscodes vorgeschlagen, kann zu einer falschen Schlussfolgerung führen. Im Allgemeinen mag ich die Verwechslung von Transport- und Anwendungsschicht bei der Verwendung der Statuscodes nicht.
SCI

Antworten:

220

Zuerst war ich versucht, meinen Anwendungsfehler mit 200 OK und einer bestimmten XML-Nutzlast zurückzugeben (dh zahlen Sie uns mehr und Sie erhalten den Speicher, den Sie benötigen!), Aber ich habe aufgehört, darüber nachzudenken, und es scheint zu seifen (/ Achselzucken vor Entsetzen).

Ich würde keine 200 zurückgeben, wenn an der Anfrage wirklich nichts auszusetzen wäre. Ab RFC2616 bedeutet 200 "die Anforderung war erfolgreich".

Wenn das Speicherkontingent des Clients überschritten wurde (aus welchem ​​Grund auch immer), würde ich eine 403 (Verboten) zurückgeben:

Der Server hat die Anfrage verstanden, weigert sich jedoch, sie zu erfüllen. Die Autorisierung hilft nicht und die Anfrage sollte nicht wiederholt werden. Wenn die Anforderungsmethode nicht HEAD war und der Server veröffentlichen möchte, warum die Anforderung nicht erfüllt wurde, sollte der Grund für die Ablehnung in der Entität beschrieben werden. Wenn der Server diese Informationen dem Client nicht zur Verfügung stellen möchte, kann stattdessen der Statuscode 404 (Nicht gefunden) verwendet werden.

Dies teilt dem Client mit, dass die Anforderung in Ordnung war, aber fehlgeschlagen ist (etwas, das eine 200 nicht tut). Dies gibt Ihnen auch die Möglichkeit, das Problem (und seine Lösung) im Antworttext zu erläutern.

Welche anderen spezifischen Fehlerbedingungen hatten Sie im Sinn?

Reiches Apodaca
quelle
6
Sollte ich meine detaillierte Fehlermeldung in den Text aufnehmen, dh. ein XML-Code / String-Paar? Wie gehen Kunden am besten damit um? Ich weiß zum Beispiel, dass C # WebRequest-basierte Clients "Bad Request" oder "Forbidden" auslösen und den Antworttext nicht angeben.
Remus Rusanu
18
Der Körper eines 403 "sollte" die Details des Fehlers enthalten. Ob ein Kunde bereit ist, die Informationen zu nutzen, ist eine andere Geschichte. Es ist am sinnvollsten, wenn dieses Format mit dem Format für alle anderen Nutzdaten (z. B. XML, JSON) identisch ist.
Rich Apodaca
1
... und wenn die Details im 403 nicht zurückgegeben werden, kann stattdessen ein 404 "verwendet" werden (klingt für mich jedoch nicht nach der besten Option).
Rich Apodaca
6
Die Option 404 gilt für den Fall, dass ein 403 möglicherweise Details zu der Anwendung anzeigt, über die nicht autorisierte Benutzer nichts wissen sollen. Wenn ein nicht administrativer Benutzer beispielsweise auf eine URL nur für Administratoren trifft, möchten Sie diesen Benutzer möglicherweise nicht zu wissen, dass es sich um eine gültige URL für Administratoren usw. handelt. In diesem Fall ist der 403 jedoch völlig angemessen.
Greg Campbell
16
Ich halte dies für eine ziemlich wenig hilfreiche Antwort. Ich hätte gedacht, der wichtigere Aspekt ist, ob nur Status verwendet werden sollen oder ob die Fehlerinformationen in der Nutzlast zurückgegeben werden sollen oder beides usw. Und dann, wie die Informationen in die Nutzlast aufgenommen werden sollen. Der verwendete spezifische Status bezieht sich nur auf einen bestimmten Aspekt der Frage.
Manachi
584

Eine großartige Ressource, um den richtigen HTTP-Fehlercode für Ihre API auszuwählen: http://www.codetinkerer.com/2015/12/04/choosing-an-http-status-code.html

Ein Auszug aus dem Artikel:

Wo soll man anfangen:

Geben Sie hier die Bildbeschreibung ein

2XX / 3XX:

Geben Sie hier die Bildbeschreibung ein

4XX:

Geben Sie hier die Bildbeschreibung ein

5XX:

Geben Sie hier die Bildbeschreibung ein

Omar Ali
quelle
1
422 Ist speziell eine WebDAV-Erweiterung. Ich denke das sollte nicht hier sein.
Mario
@Mario In Ruby on Rails-APIs ist es idiomatisch, 422 als Antwort auf die hier angegebenen Bedingungen zurückzugeben. Es ist schon viel Gutes, diesem Ansatz zu folgen. Wofür würden Sie die Verwendung von 422 ersetzen?
Kelsey Hannan
reguläre alte 400
Andbdrew
Vielen Dank. Was bedeutet "Verlassen Sie das Internet wütend?"?
RoutesMaps.com
@ Crimean.us google.com/search?q=define+rage-quit
Omar Ali
87

Die Hauptauswahl ist, ob Sie den HTTP-Statuscode als Teil Ihrer REST-API behandeln möchten oder nicht.

Beide Möglichkeiten funktionieren gut. Ich bin damit einverstanden, dass eine der Ideen von REST genau genommen darin besteht, dass Sie den HTTP-Statuscode als Teil Ihrer API verwenden sollten (geben Sie 200 oder 201 für einen erfolgreichen Vorgang und 4xx oder 5xx zurück, abhängig von verschiedenen Fehlerfällen) Es gibt keine REST-Polizei. Du kannst machen was du willst. Ich habe weitaus ungeheuerlichere Nicht-REST-APIs gesehen, die als "RESTful" bezeichnet wurden.

An dieser Stelle (August 2015) empfehle ich, dass Sie den HTTP-Statuscode als Teil Ihrer API verwenden. Es ist jetzt viel einfacher, den Rückkehrcode zu sehen, wenn Frameworks verwendet werden als in der Vergangenheit. Insbesondere ist es jetzt einfacher, den Fall der Nicht-200-Rückgabe und den Körper der Nicht-200-Antworten zu sehen als in der Vergangenheit.

Der HTTP-Statuscode ist Teil Ihrer API

  1. Sie müssen sorgfältig 4xx-Codes auswählen, die Ihren Fehlerbedingungen entsprechen. Sie können eine Rest-, XML- oder Klartextnachricht als Nutzlast einfügen, die einen Untercode und einen beschreibenden Kommentar enthält.

  2. Die Clients müssen ein Software-Framework verwenden, mit dem sie den Statuscode auf HTTP-Ebene erhalten. Normalerweise machbar, nicht immer einfach.

  3. Die Clients müssen zwischen HTTP-Statuscodes, die auf einen Kommunikationsfehler hinweisen, und Ihren eigenen Statuscodes, die auf ein Problem auf Anwendungsebene hinweisen, unterscheiden.

Der HTTP-Statuscode ist NICHT Teil Ihrer API

  1. Der HTTP-Statuscode lautet immer 200, wenn Ihre App die Anfrage erhalten und dann geantwortet hat (sowohl Erfolgs- als auch Fehlerfälle).

  2. ALLE Ihre Antworten sollten "Umschlag" - oder "Kopf" -Informationen enthalten. Typischerweise so etwas wie:

    Envelope_ver: 1.0
    Status: # Verwenden Sie beliebige Codes. Reservieren Sie einen Code für den Erfolg.
    msg: "ok" # Eine menschliche Zeichenfolge, die den Code widerspiegelt. Nützlich zum Debuggen.
    Daten: ... # Die Daten der Antwort, falls vorhanden.
  3. Diese Methode kann für Clients einfacher sein, da sich der Status für die Antwort immer an derselben Stelle befindet (keine Untercodes erforderlich), keine Begrenzung der Codes und keine Notwendigkeit, den Statuscode auf HTTP-Ebene abzurufen.

Hier ist ein Beitrag mit einer ähnlichen Idee: http://yuiblog.com/blog/2008/10/15/datatable-260-part-one/

Hauptprobleme:

  1. Stellen Sie sicher, dass Sie Versionsnummern angeben, damit Sie die Semantik der API später bei Bedarf ändern können.

  2. Dokumentieren...

Larry K.
quelle
8
Ty. Option 2 scheint jedoch wie
Seife in Ruhekleidung
138
Nein, alles durch eine 200 zu tunneln ist überhaupt nicht erholsam. Es verhindert, dass Vermittler das Ergebnis einer Operation verstehen, wodurch jede Form von Caching beendet wird. Es verbirgt die Semantik der Operation und setzt das Verständnis des Inhalts der Nachricht voraus, um einen Fehler zu verarbeiten, wodurch die in sich geschlossene Nachrichtenbeschränkung verletzt wird.
SerialSeb
13
Das Zurückgeben von Fehlerdetails mit einer 200 ist möglicherweise nicht RESTful, aber dies ist dennoch eine nützliche Antwort (wenn Sie die Bemerkung "Beide Wege sind erholsam" ignorieren) ... Der größere Punkt ist möglicherweise, dass eine RESTful-API möglicherweise nicht die beste Option für ist die Operation.
MB.
3
Es scheint ein allgemeines Verständnis zu bestehen, dass Sie mit dem HTTP-Protokoll tun können, was Sie wollen, und trotzdem "RESTy" sind, das ist falsch. Verwenden Sie das Protokoll für das, was geschrieben steht. Dies ist eine der Kernideen von REST. Der Statuscode muss also Teil Ihres Protokolls sein.
Ariel M.
Der Sinn von Statuscodes besteht darin, eine gemeinsame Sprache für das Verständnis zwischen verschiedenen Programmiersprachen, Frameworks und Ansätzen bereitzustellen. Die Bedeutung des Statuscodes ist nahezu universell: Ihr benutzerdefinierter Textkörper - der durch die benutzerdefinierte Syntax, die Ihre API-Konsumenten lernen müssen, von Natur aus komplexer wird - ist dies nicht.
Kelsey Hannan
40

Denken Sie daran, dass mehr Statuscodes vorhanden sind als in den HTTP / 1.1-RFCs definiert. Die IANA-Registrierung befindet sich unter http://www.iana.org/assignments/http-status-codes . Für den von Ihnen erwähnten Fall klingt der Statuscode 507 richtig.

Julian Reschke
quelle
3
Hmm, während auf den ersten Blick "507 Insufficient Storage" angemessen erscheint, wäre ich misstrauisch, es zu verwenden, da es als (ziemlich spezifische) WebDAV-Erweiterung gedacht ist und nicht als allgemeines "Hey, Sie haben keinen Platz mehr". Ausnahme. Trotzdem, ich nehme an, Sie könnten es benutzen.
Max
1
Nein, es ist überhaupt nicht WebDAV-spezifisch. Es gibt einen Grund, warum es eine Registrierung für HTTP-Statuscodes gibt.
Julian Reschke
26
Ich stimme 507diesem Zweck nicht zu. Meine Interpretation 507ist, dass auf dem Server nicht genügend Speicherplatz vorhanden ist und nicht, dass auf dem Konto nicht genügend Speicherplatz vorhanden ist.
Patrick
12
Ich stimme Patrick zu. 5xxFehler sind Fehler, die mit dem Server zu tun haben.
Sean
10
418: "Ich bin eine Teekanne" bedeutet, dass der Stauraum eher zu klein (wie eine Teekanne klein) als zu groß ist und daher nicht genügend Platz hat.
Steve Konves
22

Wie andere bereits erwähnt haben, ist es durchaus zulässig, eine Antwortentität in einem Fehlercode zu haben.

Denken Sie daran, dass 5xx-Fehler serverseitig sind, auch wenn der Client nichts an seiner Anforderung ändern kann, damit die Anforderung erfolgreich ist. Wenn das Kontingent des Clients überschritten wird, handelt es sich definitiv nicht um einen Serverfehler. Daher sollte 5xx vermieden werden.

SerialSeb
quelle
Ich würde nicht zustimmen. Kontingent überschritten wäre ein Serverfehler (5xx), weil: Die Anforderung des Clients gültig ist und erfolgreich gewesen wäre, wenn das Kontingent überschritten worden wäre, wodurch die 400-Serie ausgeschlossen wird.
Mikek3332002
4
Aber der Server hat nichts falsch gemacht.
Charlie Schliesser
19

Es gibt zwei Arten von Fehlern. Anwendungsfehler und HTTP-Fehler. Die HTTP-Fehler dienen lediglich dazu, Ihren AJAX-Handler darüber zu informieren, dass alles in Ordnung war und nicht für andere Zwecke verwendet werden sollte.

5xx Serverfehler

500 Internal Server Error
501 Not Implemented
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
505 HTTP Version Not Supported
506 Variant Also Negotiates (RFC 2295 )
507 Insufficient Storage (WebDAV) (RFC 4918 )
509 Bandwidth Limit Exceeded (Apache bw/limited extension)
510 Not Extended (RFC 2774 )

2xx Erfolg

200 OK
201 Created
202 Accepted
203 Non-Authoritative Information (since HTTP/1.1)
204 No Content
205 Reset Content
206 Partial Content
207 Multi-Status (WebDAV)

Wie Sie Ihre Anwendungsfehler entwerfen, liegt jedoch ganz bei Ihnen. Stapelüberlauf zum Beispiel sendet ein Objekt mit response, dataund messageEigenschaften. Die Antwort, die ich glaube, enthält trueoder zeigt falsean, ob die Operation erfolgreich war (normalerweise für Schreiboperationen). Die Daten enthalten die Nutzdaten (normalerweise für Lesevorgänge) und die Nachricht enthält zusätzliche Metadaten oder nützliche Nachrichten (z. B. Fehlermeldungen, wenn dies der Fall responseist false).

Aleemb
quelle
2
400 ist auch hilfreich, um auf ein Problem in der Clientanwendung hinzuweisen.
Dolmen
19

Ich weiß, dass dies für die Party extrem spät ist, aber jetzt, im Jahr 2013, haben wir einige Medientypen, um die Fehlerbehandlung auf eine allgemein verteilte (RESTful) Weise zu behandeln. Siehe "vnd.error", application / vnd.error + json ( https://github.com/blongden/vnd.error ) und "Problemdetails für HTTP-APIs", application / problem + json ( https: // tools. ietf.org/html/draft-nottingham-http-problem-05 ).

Jørn Wildt
quelle
2
Danke für die Links. Draft-Nottingham-http-Problem ist jetzt ein vorgeschlagener Standard: datatracker.ietf.org/doc/rfc7807
Seanf
9

Einverstanden. Die Grundphilosophie von REST besteht darin, die Webinfrastruktur zu nutzen. Die HTTP-Statuscodes sind das Messaging-Framework, mit dem Parteien miteinander kommunizieren können, ohne die HTTP-Nutzlast zu erhöhen. Sie sind bereits etablierte universelle Codes, die den Status der Antwort übermitteln. Um wirklich RESTful zu sein, müssen die Anwendungen dieses Framework verwenden, um den Antwortstatus zu kommunizieren.

Das Senden einer Fehlerantwort in einem HTTP 200-Umschlag ist irreführend und zwingt den Client (API-Consumer), die Nachricht zu analysieren, höchstwahrscheinlich auf nicht standardmäßige oder proprietäre Weise. Dies ist auch nicht effizient - Sie werden Ihre Clients zwingen, die HTTP-Nutzdaten jedes Mal zu analysieren, um den "echten" Antwortstatus zu verstehen. Dies erhöht die Verarbeitung, erhöht die Latenz und schafft eine Umgebung, in der der Client Fehler machen kann.

Kingz
quelle
3
Unabhängig davon, ob Sie eine erfolgreiche Antwort oder eine Fehlerantwort haben, werden Sie die Antwort höchstwahrscheinlich analysieren. Wenn es sich um einen Fehler handelt, möchten Sie ihn analysieren, um die Fehlermeldung anzuzeigen. Fehlerantworten sind im Allgemeinen klein und schnell zu analysieren. Ich denke nicht, dass wir uns Gedanken darüber machen sollten, zu optimieren, um das Parsen von Fehlerantworten zu vermeiden. Würden Sie die Fehlerantwort einfach wegwerfen, ohne sie zu analysieren? Meiner Meinung nach unklug.
AgilePro
3
Wenn Sie ein 200 OK erhalten, können Sie es abhängig von Ihren Geschäftsregeln auch nicht analysieren. Es geht nicht darum, ob wir es jederzeit analysieren oder nicht. Der Punkt ist die Absicht - was ist die Absicht von 200 OK? Sie beschädigen die Absicht, indem Sie Fehlermeldungen senden, die in 200 OK eingeschlossen sind.
Kingz
1
"Was ist die Absicht von 200 OK?" - Anzeige des Erfolgs der Transportschicht. Die Anfrage wurde erfolgreich empfangen und beantwortet. Es gab nur ein anwendungsspezifisches Problem, das nichts mit HTTP zu tun hatte. +++ Umgekehrt: Wenn Sie 404 in der REST-Welt senden, wurde etwas nicht gefunden, möglicherweise ist die URL einfach falsch oder die zu verarbeitende Ressource oder etwas anderes wurde nicht gefunden. Ohne die Nachricht zu analysieren, können Sie nicht. IMHO REST verschmilzt nur Schichten.
Maaartinus
Konflikt ist die Norm. Es bietet Ihnen eine Syntax, die zu Ihrer Argumentation passt, und gibt Ihnen die Möglichkeit, sich auf die Geschäftsschicht zu konzentrieren. Einig über den Transport später Statuskommunikation - das war in erster Linie der Zweck - REST wurde nicht gleichzeitig mit HTTP erfunden / vorgeschlagen - es kam später und entschied sich einfach, die vorhandene Infrastruktur zu nutzen, um STAATEN und ihre ÄNDERUNGEN darzustellen.
Kingz
5

Bitte halten Sie sich an die Semantik des Protokolls. Verwenden Sie 2xx für erfolgreiche Antworten und 4xx, 5xx für Fehlerantworten - seien es Ihre geschäftlichen Ausnahmen oder andere. Wäre die Verwendung von 2xx für eine Antwort der beabsichtigte Anwendungsfall im Protokoll gewesen, hätten sie überhaupt keine anderen Statuscodes.

rahil008
quelle
3

Vergessen Sie nicht die 5xx-Fehler auch für Anwendungsfehler.

In diesem Fall was ist mit 409 (Konflikt)? Dies setzt voraus, dass der Benutzer das Problem durch Löschen gespeicherter Ressourcen beheben kann.

Andernfalls funktioniert möglicherweise auch 507 (nicht ganz Standard). Ich würde 200 nicht verwenden, es sei denn, Sie verwenden 200 für Fehler im Allgemeinen.

Kathy Van Stone
quelle
-2

Wenn das Client-Kontingent überschritten wird, handelt es sich um einen Serverfehler. Vermeiden Sie in diesem Fall 5xx.

feste Rente
quelle
3
Warum sollten Sie die Fehler der 5xx-Serie vermeiden, wenn es sich um Serverfehler handelt?
Mikek3332002
7
'Client-Kontingent überschritten' ist imho kein Serverfehler, sondern eine Client-Einschränkung und sollte unter 4xx liegen.
MyGGaN