Soll ich einen HTTP 400-Status (Bad Request) zurückgeben, wenn ein Parameter syntaktisch korrekt ist, aber eine Geschäftsregel verletzt?

56

Angenommen, ich habe einen REST-Endpunkt, der eine Ganzzahl als Parameter verwendet:

/makeWaffles?numberOfWaffles=3

In diesem Fall möchte ich, dass die Zahl positiv ist, da ich keine negative Anzahl von Waffeln herstellen kann (und das Anfordern von 0 Waffeln ist Zeitverschwendung). Ich möchte also jede Anfrage ablehnen, die keine positive Ganzzahl enthält. Ich möchte auch eine Anfrage ablehnen, die eine maximale Ganzzahl überschreitet (sagen wir mal, es ist MAX_INTEGER).

Soll ich für den Fall, dass jemand eine nicht positive Anzahl von Waffeln anfordert, einen HTTP 400-Status (Bad Request) zurückgeben? Mein erster Gedanke ist ja: Es ist keine gültige Nummer für mich, um die Anfrage abzuschließen. Der RFC nennt jedoch keine Geschäftsregeln als Grund, es zu werfen:

Der Statuscode 400 (Bad Request) gibt an, dass der Server die Anforderung aufgrund eines als Clientfehler wahrgenommenen Problems (z. B. fehlerhafte Anforderungssyntax, ungültige Anforderungsnachrichten oder irreführendes Anforderungsrouting) nicht verarbeiten kann oder wird.

Eine Geschäftsregel fällt nicht unter eines dieser drei Beispiele. Es ist syntaktisch korrekt, richtig eingerahmt und täuscht nicht über das Weiterleiten von Anforderungen.

Soll ich also einen HTTP 400-Status (Bad Request) zurückgeben, wenn ein Parameter syntaktisch korrekt ist, aber eine Geschäftsregel verletzt? Oder gibt es einen angemesseneren Status für die Rückgabe?

Donnerschmiede
quelle

Antworten:

38

Dies ist eine große Frage, die angesichts des historischen Kontexts (und der scheinbar widersprüchlichen Definitionen) der HTTP-Rückkehrcodes immer noch von hoher Relevanz ist. Auch bei den Antworten auf diese Frage gibt es widersprüchliche Definitionen. Dies kann durch chronologische Bewegung geklärt werden.

RFC 2616 (Juni 1999)

10.4.1 400 Bad Request

Die Anforderung konnte vom Server aufgrund einer fehlerhaften Syntax nicht verstanden werden. Der Client sollte die Anfrage NICHT ohne Änderungen wiederholen.

Ab diesem RFC galt dieser Statuscode speziell nur für syntaktisch ungültige Anforderungen. Es gab eine Lücke in den Statuscodes für die semantische Validierung. Als RFC 4918 auf den Markt kam, entstand ein neuer Code.

RFC 4918 (Juni 2007)

11.2. 422 Nicht verarbeitbare Einheit

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.

422 Unprocessable Entity wurde erstellt, um die Lücke der semantischen Validierung in der ursprünglichen Spezifikation der 4xx-Statuscodes zu schließen. 2014 kam jedoch ein weiterer relevanter RFC hinzu, in dem 400 nicht mehr syntaxspezifisch verallgemeinert wurden .

RFC 7231 (Juni 2014, RFC 2616 explizit veraltet)

6.5.1. 400 Ungültige Anfrage

Der Statuscode 400 (Bad Request) gibt an, dass der Server die Anforderung aufgrund eines als Clientfehler wahrgenommenen Problems (z. B. fehlerhafte Anforderungssyntax, ungültige Anforderungsnachrichten oder irreführendes Anforderungsrouting) nicht verarbeiten kann oder wird.

Beachten Sie, dass die 422-Beschreibung besagt, dass der Grund für die Unangemessenheit von 400 darin besteht, dass 400 (ab RFC 2616) nur für eine falsche Anforderungssyntax zurückgegeben werden sollte. Doch wie von RFC 7231, die strengen Syntax-Fehlerdefinition nicht mehr auf 400 .

Zurück zur vorliegenden Frage: Während 422 in diesem Zusammenhang technisch spezifischer ist, konnte ich sehen, dass entweder 400 oder 422 für die semantische Validierung von API-Parametern verwendet werden. Ich zögere, 422 in meinen eigenen APIs zu verwenden, da die Definition von 422 zu diesem Zeitpunkt technisch veraltet ist (obwohl ich nicht weiß, ob dies offiziell irgendwo anerkannt ist). Der Artikel, auf den in Frans Antwort verwiesen wird, die die Verwendung von 422 fördert, wurde 2012 geschrieben, zwei Jahre bevor RFC 7231 HTTP 400 klarstellte.

Kyle McVay
quelle
42

Ich habe die erste Antwort gelesen und war nicht wirklich damit einverstanden, weil eine schlechte Anfrage (400) zumindest in meiner Lektüre bedeutet: "Ich kann Ihre Anfrage nicht einmal bearbeiten, weil etwas grundlegend falsch ist." Und ich habe diesen Beitrag gefunden, der die Rückgabe eines 422 rechtfertigt.

von IETF

422 Unprocessable Entity (WebDAV; RFC 4918) Die Anforderung war ordnungsgemäß aufgebaut, konnte jedoch aufgrund semantischer Fehler nicht befolgt werden

Dies scheint eine angemessenere Antwort zu sein, da Ihre Anfrage wohlgeformt ist, aber Ihre Validierungsregeln nicht erfüllt.

Fran
quelle
5
Ich habe gehört, es sei beschrieben als "400 bedeutet schlechte Syntax, 422 bedeutet schlechte Semantik."
Cbojar
33
Alle x00-Codes sind generische Codes, die alle abfangen. Eine 400 ist nicht unangemessen , nur weniger spezifisch .
Jack
1
Gute Antwort, aber die Antwort von @GoFree macht für mich mehr Sinn.
Ewerton
2
Es gibt ein starkes Argument für die Rücksendung von Codes, das jeder kennt. Absolut jeder wird nachsehen müssen 422, und ich wette, dass die meisten immer noch nicht wissen, was sie davon halten sollen.
Sylvanaar
8

Ja, Eingaben, die nicht dem implizierten Vertrag des Endpunkts entsprechen, sind "als Clientfehler wahrgenommen" und sollten 400 zurückgeben.

Die Ausnahme ist, wenn die Geschäftsregel sicherheitsrelevant ist (dann 401 Unauthorizedoder 403 Forbiddenbesser wäre). Alternativ, wenn das Senden einer 400 Informationen über die Existenz von etwas verlieren würde, ist eine 404 Not Foundmöglicherweise geeigneter.

Telastyn
quelle
8

Nein, das solltest du nicht. HTTP-Codes sind für die HTTP-Schicht Ihrer Anwendung bestimmt. Geschäftsregeln sind eine völlig andere Ebene und anwendungsspezifisch. Sie müssen daher ein eigenes "Protokoll" erstellen.

Stellen Sie sich eine Apokalypse vor und Sie müssen vom HTTP-Protokoll zur Verwendung von Pigeons wechseln. Tauben haben keine Rückkehrcodes, daher müssten Sie Ihre Geschäftsschicht ändern, um dem Rechnung zu tragen. Ihr Unternehmen hat sich jedoch nicht wirklich verändert, sodass Sie die Business-Schicht nicht ändern müssen. Es zeigt eine enge Kopplung zwischen diesen beiden Schichten (Transport und Geschäft).

Zurück zur Frage: Geben Sie "200 OK" mit einem Text zurück, der beschreibt, was mit der Anforderung geschehen ist. In der Spezifikation heißt es eindeutig:

https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1 .

200 OK

Die Anfrage war erfolgreich. Die Informationen mit der Antwort zurückgegeben sind abhängig von dem Verfahren , das in der Anforderung verwendet wird , zum Beispiel

POST eine Entität, die das Ergebnis der Aktion beschreibt oder enthält;

War Ihre HTTP-Anfrage erfolgreich? Ja, der Webserver weiß, wie er mit dieser Anforderung umgehen soll (z. B. an den Serverteil Ihrer Anwendung weiterleiten). Der Webserver leitet diese Anforderung dann an den Serverteil Ihrer Anwendung weiter, der die POST-Daten verarbeitet (in Ihrem Fall validiert) und eine normale Antwort (im Hauptteil einer HTTP-Antwort) an den Client-Teil Ihrer Anwendung zurückgibt . Diese Antwort vom Serverteil der Anwendung kann entweder "Großartig, die von Ihnen gesendeten Daten sind gültig" oder "Es tut mir leid, die von Ihnen gesendeten Daten sind ungültig" sein. Und es liegt an Ihrem Kunden, zu verstehen, was die Antwort bedeutet.

PS: "400 Bad Request" bedeutet, dass der Webserver nicht verstanden hat, was Sie von ihm wollen. Dies bedeutet, dass Ihr Serverteil Ihrer Anwendung die Anfrage nicht einmal erhalten hat. Zumindest ist das so gemeint :-)

EDIT : Mir ist gerade aufgefallen, dass Sie eine GET-Anfrage machen, nicht POST. Dies ist eine schlechte Idee, da GET den Status der Anwendung nicht ändern sollte. GET soll einfach Daten vom Server abrufen. Aber in Ihrer Anfrage ändern Sie tatsächlich den Status der Anwendung, sodass Sie POST wirklich verwenden sollten.

Geh frei
quelle
1
Ja, in diesem Fall ist die Rückgabe von 404 in Ordnung. Ich sage nicht, dass Server immer 200 OK mit einer Erklärung im Körper senden sollte.
GoFree
Bessere Erklärung, die ich bisher gesehen habe. Ich habe die gleiche Frage und es sieht so aus, als würde sich jedes Wort von mir und Ihnen unterscheiden. @GoFree
Ewerton
@GoFree Dies ist eine wirklich gute Antwort, um das API-Design zu überdenken. Aber ist es nicht so, dass wir HTTP und seinen Antwortcode als wichtigen Bestandteil der Ebene der Geschäftsregeln verwenden, wenn wir eine REST-API verwenden?
Thomas Lauria
1
@ Thomas Lauria Ich habe noch keine ordnungsgemäße Implementierung der RESTFUL-API gesehen. Die REST-API ist jedoch heute ein Modewort, sodass jedes Unternehmen sie verwenden muss (das Wort, nicht die Technologie), ohne das Konzept dahinter zu verstehen. Also ja, es wird überall falsch verwendet. Normalerweise erstellen Programmierer keine REST-API, sondern eine HTTP-API oder eine API ÜBER HTTP. Tatsächlich ist eine der wenigen guten RESTFUL-Implementierungen das HTTP selbst :)
GoFree
1
Die Verwendung von 200-OK ist besonders logisch, wenn die Anwendung ein "Fehler" -Feld im Antworttext enthält, um Fehler auf Unternehmensebene zu beschreiben, z. B. zu hohe oder zu niedrige Eingabewerte oder fehlende, nicht vorrätige Produkte usw.
Roland,
-3

Ich bin mir nicht sicher, ob alle zustimmen würden, aber wir verwenden 409 - Conflict. Viele geben an, dass der 409 eher ein Konflikt mit dem Systemstatus ist, aber wir haben die Interpretation akzeptiert, dass ein Konflikt von Datenwerten, die außerhalb des akzeptierten Bereichs liegen, vom Anforderer behoben werden kann, und eine akzeptable Verwendung von 409. 422 Ich halte dies für angemessen ist korrekt aufgebaut, kann aber nicht wie gewünscht bearbeitet werden. Ich meine jedoch, wenn Sie keine Vielzahl von Antworten implementieren möchten, ist es immer noch akzeptabel, nur eine 400 zu geben.

dlb
quelle
5
409 bedeutet, dass "der Zustand, in den Sie dies einfügen möchten, in Konflikt mit dem Zustand steht, in den ein anderer Client dies einfügen möchte". Dies dient zum Blockieren von gleichzeitigen Schreibvorgängen (z. B. mithilfe von ETags).
Jack