Sollten HTTP-Statuscodes verwendet werden, um Geschäftslogikfehler auf einem Server darzustellen?

20

Ich bin an einer Kreuzung mit einigen API-Design für einen Client (JS in einem Browser), um mit einem Server zu sprechen. Wir verwenden HTTP 409-Konflikt, um das Fehlschlagen einer Aktion aufgrund einer aktivierten Sicherheitssperre darzustellen. Das Satefy-Schloss verhindert, dass Entwickler versehentlich Änderungen an den Produktionssystemen unserer Kunden vornehmen. Ich wurde damit beauftragt, 409s auf dem Client etwas eleganter zu behandeln, um anzuzeigen, warum ein bestimmter API-Aufruf fehlgeschlagen ist.

Meine Lösung bestand darin, die Fehlerbehandlungsroutinen aller unserer AJAX-Aufrufe zu bündeln, die eine Benachrichtigung auf dem Client anzeigen, wenn aufgrund von 409 etwas ausfällt. Dies ist in Ordnung und funktioniert gut zusammen mit anderen 4XX- und 5XX-Fehlern, die denselben Mechanismus verwenden.

Es ist ein Problem aufgetreten, bei dem einer unserer Route-Handler auf einen Fehler in der Geschäftslogik mit 409s reagiert. Mein AJAX-Wrapper meldet, dass die Sicherheitssperre aktiviert ist, während der vorhandene Failure-Handler des Clients meldet, was (seiner Meinung nach) das Problem auf dem Körper basiert der Antwort. Eine einfache Lösung wäre, entweder die Antwort des Handlers oder den Statuscode zu ändern, den wir zur Darstellung des Sicherheitsschlosses verwenden.

Was mich an den Scheideweg bringt: Sollen HTTP-Statuscodes überhaupt zur Darstellung von Fehlern in der Geschäftslogik verwendet werden? Diese Frage befasst sich mit dem gleichen Problem, mit dem ich konfrontiert bin, hat aber nicht viel Anklang gefunden. Wie in der verknüpften Antwort vorgeschlagen, neige ich dazu, HTTP 200 OK mit einem geeigneten Textkörper zu verwenden, um Fehler in der Geschäftslogik darzustellen.

Hat hier jemand eine starke Meinung? Kann mich jemand davon überzeugen, dass dies der falsche Weg ist, ein Versagen darzustellen?

Joe Shanahan
quelle
3
Ich zögere, meine einfache Meinung als Antwort zu posten. Kurz gesagt: Ich vermeide generell die Verwendung von HTTP-Statuscodes zur Darstellung von Geschäftsfehlern. Sie sollten sich nur auf den Status der Kommunikation zwischen Client und Server beziehen. Ein geeigneter Statuscode für die Rückgabe von Validierungs- oder Geschäftslogikfehlern wäre 400 Bad Request. Der Grund für diese Trennung ist, dass zukünftige Systeme, Entwickler oder Leser von Dokumenten durch Ihre Abweichung vom weltweiten Standard verwirrt werden können.
Ivo Coumans
@IvoCoumans: Bitte mache dies zu einer Antwort, damit ich sie unterstützen kann. 400 Bad Requestals Decke HTTP-Code scheint am besten, um Business-Logik-Fehler als Klasse abzudecken.
9000
Persönliche Vorlieben, aber ich verwende sie eher, 400 Bad Requestwenn Daten fehlen oder nicht gelesen / analysiert werden können. Dh die Anforderungsdaten selbst sind in irgendeiner Weise schlecht.
Kasey Speakman
Bitte erläutern Sie, was Sie unter "Fehler in der Geschäftslogik" verstehen. Das ist sehr vage. Meinen Sie damit eine Eingabe, die gemäß den (korrekten) Datenüberprüfungen ungültig ist, eine Eingabe, die möglicherweise zu einem anderen Zeitpunkt gültig ist, aber im aktuellen Status ungültig ist, oder einen Fehler in der Geschäftslogik, bei dem eine gültige Eingabe abgelehnt wird?
jpmc26
@ jpmc26 Ich war absichtlich vage, da es eine allgemeine Frage war. Die Server haben die Anfrage gut bewältigt, sind jedoch zu dem Schluss gekommen, dass die Abfrage / Behauptung keinen Sinn ergibt.
Joe Shanahan

Antworten:

19

Kasey deckt den Hauptpunkt ab.

Die Schlüsselidee in jeder Web-API: Sie passen Ihre Domain so an, dass sie wie ein Dokumentenspeicher aussieht. GET / PUT / POST / DELETE usw. sind alle Arten der Interaktion mit dem Dokumentenspeicher.

So eine Art des Denkens über das, was Codes zu verwenden, ist zu verstehen , was die analoge Operation in einem Dokumentenspeicher ist, und was diese Fehler wie in diesen analogen aussehen würden.

2xx ist völlig ungeeignet

Die Statuscode-Klasse 2xx (Erfolgreich) gibt an, dass die Anforderung des Clients erfolgreich empfangen, verstanden und akzeptiert wurde.

5xx ist auch ungeeignet

Die Statuscode-Klasse 5xx (Server Error) gibt an, dass der Server den Fehler erkannt hat

In diesem Fall hat der Server keinen Fehler gemacht. Es ist bekannt, dass Sie diese Ressource derzeit nicht auf diese Weise ändern sollten.

Fehler in der Geschäftslogik (was bedeutet, dass die Geschäftsinvariante die vorgeschlagene Bearbeitung zu diesem Zeitpunkt nicht zulässt) sind wahrscheinlich 409

Der Statuscode 409 (Konflikt) gibt an, dass die Anforderung aufgrund eines Konflikts mit dem aktuellen Status der Zielressource nicht abgeschlossen werden konnte. Dieser Code wird in Situationen verwendet, in denen der Benutzer den Konflikt möglicherweise lösen und die Anforderung erneut senden kann. Der Server SOLLTE eine Nutzlast generieren, die genügend Informationen enthält, damit ein Benutzer die Ursache des Konflikts erkennen kann.

Beachten Sie das letzte Bit: Die Nutzlast der Antwort 409 sollte dem Verbraucher Informationen über die aufgetretenen Probleme übermitteln und im Idealfall Hypermedia-Steuerelemente enthalten, die den Verbraucher zu den Ressourcen führen, die zur Lösung des Konflikts beitragen können.

Meine Lösung bestand darin, die Fehlerbehandlungsroutinen aller unserer AJAX-Aufrufe zu bündeln, die eine Benachrichtigung auf dem Client anzeigen, wenn aufgrund von 409 etwas ausfällt. Dies ist in Ordnung und funktioniert gut zusammen mit anderen 4XX- und 5XX-Fehlern, die denselben Mechanismus verwenden.

Und ich würde darauf als das Problem hinweisen; Ihre Implementierung beim Kunden ging davon aus, dass der Statuscode ausreicht, um das Problem zu definieren. Stattdessen sollte Ihr Client-Code die Nutzdaten überprüfen und auf die dort verfügbaren Informationen reagieren.

So würde es immerhin ein Dokumentenspeicher tun

409  Conflict

your proposed change has been declined because ${REASON}.  
The following resolution protocols are available: ${LINKS[@]})

Der gleiche Ansatz mit a 400 Bad Requestwäre auch akzeptabel; was ungefähr "übersetzt in" bedeutet. Bei Ihrer Anfrage ist ein Problem aufgetreten. Wir müssen nicht herausfinden, welcher Statuscode am besten zu Ihnen passt. Einzelheiten finden Sie in der Nutzlast. "

Ich würde 422 verwenden. Die Eingabe ist gültig, daher ist 400 nicht der richtige Fehlercode

Die WebDAV-Spezifikation enthält diese Empfehlung

Der Statuscode 422 (Nicht verarbeitbare Entität) bedeutet, dass der Server den Inhaltstyp der Anforderungsentität versteht (daher ist ein Statuscode 415 (Nicht unterstützter Medientyp) ungeeignet) und die Syntax der Anforderungsentität korrekt ist (daher eine 400 (ungültige Anforderung) ) Der Statuscode ist unangemessen.) Die enthaltenen Anweisungen konnten jedoch nicht verarbeitet werden. Diese Fehlerbedingung kann beispielsweise auftreten, wenn ein XML-Anforderungstext wohlgeformte (dh syntaktisch korrekte), aber semantisch fehlerhafte XML-Anweisungen enthält.

Ich glaube nicht, dass das ganz passend ist (obwohl ich zustimme, dass es 400als Alternative einige Zweifel aufwirft). Meine Interpretation ist, dass 422"Sie haben die falsche Entität gesendet", wohin 409"Sie haben die Entität zur falschen Zeit gesendet".

Anders ausgedrückt: 422Weist auf ein Problem mit der Anforderungsnachricht 409hin, das isoliert betrachtet wird, und weist darauf hin, dass die Anforderungsnachricht mit dem aktuellen Status der Ressource in Konflikt steht.

Die Diskussion von Ben Nadal über 422 kann nützlich sein, um darüber nachzudenken.

VoiceOfUnreason
quelle
5
" Sie passen Ihre Domain so an, dass sie wie ein Dokumentenspeicher aussieht " - ich würde es begrüßen, wenn die Leute dies lesen und alle Konsequenzen und Implikationen verstehen, bevor sie sich für (oder gegen) REST entscheiden. Ja wirklich.
JensG
"Fehler in der Geschäftslogik" klingt für mich nach "ungültiger Eingabe", was normalerweise eine gerade Zahl von 400 ist, da es keinen genaueren Fehlercode dafür gibt. Wenn es nicht die Eingabe ist, die ungültig ist, hat der Server einen Fehler und 500 ist angemessen. Ihre Antwort scheint zu viel über die Natur eines "Geschäftslogikfehlers" anzunehmen.
jpmc26
Ich würde 422 verwenden. Die Eingabe ist gültig, daher ist 400 nicht der richtige Fehlercode
Konrad
19

Nach meiner Erfahrung reichen HTTP-Fehlercodes nicht aus, um Geschäftsfehler darzustellen. Sie sind jedoch nützlich, um Fehlerklassen darzustellen.

Daher würde ich empfehlen, HTTP-Fehlercodes für Fehlerkategorien zu verwenden, aber einen bestimmten Fehler für Geschäftslogikfehler auszuwählen (z. B. 409 Konflikt ... 200 OK würde hier irreführend sein) und Daten in die Antwort aufzunehmen, die den bestimmten Geschäftsfehler angeben . Stellen Sie sicher, dass dies Teil des Antwortinhalts und nicht des Statustexts ist, da einige Browser benutzerdefinierten Statustext ignorieren. Die Sprache, die ich gerne verwende, verfügt über Unionstypen, die sich zur Darstellung von Nachrichten eignen. Sie können aber auch String-Konstanten für Fehlerfälle definieren.

Beispiele

// error with text response
409 Conflict "safety_lock_engaged"
409 Conflict "customer_not_eligible_for_selected_discount"
// warning with JSON response
202 Accepted { "backorderedProductIds": [ 37, 476 ] }
Kasey Speakman
quelle
Die 4xx-Statuscodes über 400 haben eine ganz bestimmte Bedeutung. Wählen Sie 400, wenn Ihr Fall von den anderen nicht speziell abgedeckt wird.
jpmc26
@ jpmc26 Wenn ich die Statuscodes nicht auf diese Weise verwende, werden sie niemals verwendet. Aber zögern Sie nicht, sie in Ihren Antworten richtig und richtig zu verwenden.
Kasey Speakman
In gewissem Sinne hast du recht. Sie werden nie benutzt. Die für die spezifischen Codes gewählten Bedeutungen scheinen für die meisten Anwendungen keine alltäglichen Anwendungsfälle zu sein. Das ist okay. Es gibt viele Ausnahmen, in denen wir niemals Code schreiben, der abgefangen werden muss.
jpmc26
@ jpmc26 Naja, Ausnahmen sind nicht das beste Modell, dem man folgen kann . Aber sicher, mach weiter.
Kasey Speakman
Nicht werfen oder für spezifische Ausnahme Fangarten ist der Analog nicht immer bestimmte HTTP - Codes oder jegliche andere Fehlercodes. Ich nahm an, dass dies offensichtlich wäre. Ob ein Ausnahmemodell "das Beste" ist, ist absolut irrelevant.
jpmc26
5

Im Allgemeinen würde ich die Verwendung von HTTP-Statuscodes vermeiden, um bestimmte Geschäftslogikfehler darzustellen. Dies liegt daran, dass sie bereits eine semantische Bedeutung haben, die durch den weltweiten Standard definiert wird. Andere Systeme, neue Entwickler usw. werden durch Ihre Abweichung vom Standard verwirrt.

Was ich in jüngster, ähnlicher Forschung herausgefunden habe, war, dass es allgemein akzeptiert wird, es 400 Bad Requestim Falle von Validierungsfehlern und dergleichen zu verwenden. Auf diese Weise verwenden Sie einen Statuscode für alle Geschäftslogikfehler.

Sollte übrigens 409verwendet werden, wenn sich eine Ressource geändert hat, während Sie sie bearbeitet und erneut gespeichert haben.

Ivo Coumans
quelle
4

Sie können "Bad Request" verwenden und die ID der verletzten Geschäftsregel sowie einige weitere Details zum Hauptteil der Antwort angeben.

noneconnex
quelle
Ich weiß nicht, ob dies falsch gewählt wurde. Auf diese Weise können Unternehmen Geschäftsausnahmen zurückgeben.
Skadoosh