521 Stimmen

400 vs 422 Antwort auf POST von Daten

Ich versuche herauszufinden, welcher Statuscode in verschiedenen Szenarien mit einer "REST-ähnlichen" API, an der ich arbeite, zurückgegeben werden soll. Angenommen, ich habe einen Endpunkt, der das POSTen von Käufen im JSON-Format ermöglicht. Es sieht so aus:

{
    "account_number": 45645511,
    "upc": "00490000486",
    "price": 1.00,
    "tax": 0.08
}

Was sollte ich zurückgeben, wenn der Client mir "sales_tax" sendet (anstelle von "tax"). Derzeit gebe ich eine 400 zurück. Aber ich habe angefangen, an mir selbst zu zweifeln. Sollte ich wirklich eine 422 zurückgeben? Ich meine, es handelt sich um JSON (was unterstützt wird) und es ist gültiges JSON, es enthält einfach nicht alle erforderlichen Felder.

567voto

Kristian Glass Punkte 36033

400 Bad Request scheint nun der beste HTTP/1.1-Statuscode für Ihren Anwendungsfall zu sein.

Zur Zeit Ihrer Frage (und meiner ursprünglichen Antwort) war RFC 7231 noch nicht vorhanden; zu diesem Zeitpunkt widersprach ich 400 Bad Request, weil RFC 2616 sagte (mit meiner Hervorhebung):

Der Server konnte die Anforderung aufgrund einer fehlerhaften Syntax nicht verstehen.

und die von Ihnen beschriebene Anforderung ist syntaktisch gültiges JSON in syntaktisch gültigem HTTP, und daher hat der Server keine Probleme mit der Syntax der Anforderung.

Jedoch wurde darauf hingewiesen von Lee Saferite in den Kommentaren, dass RFC 7231, das RFC 2616 obsolet macht, diese Einschränkung nicht enthält:

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


Allerdings, vor dieser Neufassung (oder wenn Sie über RFC 7231 nur als einen derzeit nur vorgeschlagenen Standard streiten möchten), scheint 422 Unprocessable Entity kein falscher HTTP-Statuscode für Ihren Anwendungsfall zu sein, denn wie die Einleitung zu RFC 4918 sagt:

Während die von HTTP/1.1 bereitgestellten Statuscodes in der Lage sind, die meisten Fehlerbedingungen zu beschreiben, die bei WebDAV-Methoden auftreten, gibt es einige Fehler, die nicht sauber in die vorhandenen Kategorien fallen. Diese Spezifikation definiert zusätzliche Statuscodes, die für WebDAV-Methoden entwickelt wurden (Abschnitt 11)

Und die Beschreibung von 422 besagt:

Der Statuscode 422 (Unprocessable Entity) bedeutet, dass der Server den Inhaltstyp der Anforderungseinheit versteht (daher ist ein 415 (Unsupported Media Type) Statuscode unangemessen) und die Syntax der Anforderungseinheit korrekt ist (daher ist ein 400 (Bad Request) Statuscode unangemessen), aber nicht in der Lage war, die enthaltenen Anweisungen zu verarbeiten.

(Beachten Sie den Verweis auf Syntax; Ich vermute, dass 7231 auch 4918 teilweise obsolet macht)

Dies klingt genau wie Ihre Situation, aber nur für den Fall, dass Zweifel bestehen, fährt es fort zu sagen:

Zum Beispiel kann dieser Fehler auftreten, wenn ein XML-Anforderungskörper wohlgeformte (d. h. syntaktisch korrekte), aber semantisch fehlerhafte XML-Anweisungen enthält.

(Ersetzen Sie "XML" durch "JSON" und ich denke, wir können zustimmen, dass dies Ihre Situation ist)

Jetzt werden einige einwenden, dass RFC 4918 sich mit "HTTP-Erweiterungen für Web-Autorensysteme und Versionierung (WebDAV)" befasst und Sie (vermutlich) nichts mit WebDAV zu tun haben und daher keine Dinge daraus verwenden sollten.

Bei der Wahl zwischen der Verwendung eines Fehlercodes im Originalstandard, der die Situation ausdrücklich nicht abdeckt, und einem aus einer Erweiterung, der die Situation genau beschreibt, würde ich letzteres wählen.

Darüber hinaus verweist RFC 4918 Abschnitt 21.4 auf das IANA-Hypertext-Transfer-Protokoll (HTTP)-Statuscode-Verzeichnis, wo 422 zu finden ist.

Ich schlage vor, dass es absolut vernünftig ist, dass ein HTTP-Client oder Server einen Statuscode aus diesem Verzeichnis verwendet, solange dies korrekt erfolgt.


Aber seit HTTP/1.1 hat RFC 7231 Rückenwind, also verwenden Sie einfach 400 Bad Request!

170voto

Fallstudie: GitHub API

https://docs.github.com/de/rest/overview/resources-in-the-rest-api#client-errors

Vielleicht ist es eine kluge Idee, von bekannten APIs zu kopieren:

Es gibt drei mögliche Arten von Clientfehlern bei API-Aufrufen, die Anfragenkörper erhalten:

Das Senden von ungültigem JSON führt zu einer 400 Bad Request-Antwort:

HTTP/1.1 400 Bad Request
Content-Length: 35
{"message":"Probleme beim Parsen von JSON"}

Das Senden des falschen Typs von JSON-Werten führt zu einer 400 Bad Request-Antwort:

HTTP/1.1 400 Bad Request
Content-Length: 40

{"message":"Der Body sollte ein JSON-Objekt sein"}

Das Senden von ungültigen Feldern führt zu einer 422 Unprocessable Entity-Antwort:

HTTP/1.1 422 Unprocessable Entity
Content-Length: 149

{
  "message": "Validierung fehlgeschlagen",
  "errors": [
    {
      "resource": "Issue",
      "field": "title",
      "code": "missing_field"
    }
  ]
}

46voto

Filip Punkte 2836

400 Bad Request ist der richtige HTTP-Statuscode für Ihren Anwendungsfall. Der Code wird durch HTTP/0.9-1.1 RFC definiert.

Der Server konnte die Anforderung aufgrund fehlerhafter Syntax nicht verstehen. Der Client SOLLTE die Anfrage nicht wiederholen, ohne Änderungen vorzunehmen.

https://www.rfc-editor.org/rfc/rfc2616#section-10.4.1

422 Unprocessable Entity wird durch RFC 4918 - WebDav definiert. Beachten Sie, dass es einen leichten Unterschied im Vergleich zu 400 gibt, siehe unten zitierter Text.

Dieser Fehlerzustand kann auftreten, wenn ein XML-Anforderungskörper wohlgeformte (d.h. syntaktisch korrekte), aber semantisch fehlerhafte XML-Anweisungen enthält.

Um eine einheitliche Schnittstelle beizubehalten, sollten Sie 422 nur im Fall von XML-Antworten verwenden und Sie sollten auch alle von der Webdav-Erweiterung definierten Statuscodes unterstützen, nicht nur 422.

https://www.rfc-editor.org/rfc/rfc4918#page-78

Lesen Sie auch Mark Nottinghams Beitrag zu Statuscodes:

Es ist ein Fehler zu versuchen, jeden Teil Ihrer Anwendung "tief" in HTTP-Statuscodes abzubilden; in den meisten Fällen sollten Sie auf eine viel grobere Granularität abzielen. Wenn Sie unsicher sind, ist es in Ordnung, die generischen Statuscodes 200 OK, 400 Bad Request und 500 Internal Service Error zu verwenden, wenn es keine bessere Passform gibt.

Wie man über HTTP-Statuscodes nachdenken sollte

42voto

Tom Christie Punkte 32056

Um den Stand von 2015 widerzuspiegeln:

Verhaltensmäßig werden sowohl die Antwortcodes 400 als auch 422 von Clients und Intermediären gleich behandelt, daher spielt es tatsächlich keine konkrete Rolle, welchen Sie verwenden.

Ich würde jedoch erwarten, dass 400 derzeit breiter verwendet wird, und darüber hinaus machen die Erläuterungen, die die HTTPbis-Spezifikation bietet, es zu dem angemesseneren der beiden Statuscodes:

  • Die HTTPbis-Spezifikation klärt die Absicht von 400, nicht ausschließlich für Syntaxfehler zu sein. Der breitere Satz "zeigt an, dass der Server die Anfrage aufgrund eines als Clientfehler wahrgenommenen Umstands nicht verarbeiten kann oder wird" wird nun verwendet.
  • 422 ist speziell eine WebDAV-Erweiterung und wird nicht in RFC 2616 oder in der neueren HTTPbis-Spezifikation erwähnt.

Zur Einordnung: HTTPbis ist eine Überarbeitung der HTTP/1.1-Spezifikation, die versucht, Bereiche zu klären, die unklar oder inkonsistent waren. Sobald sie genehmigt ist, wird sie RFC2616 ablösen.

23voto

cdeszaq Punkte 29945

Es gibt keine korrekte Antwort, da es davon abhängt, was die Definition von "Syntax" für Ihre Anfrage ist. Das Wichtigste ist, dass Sie:

  1. Die Antwortcode(s) konsistent verwenden
  2. So viele zusätzliche Informationen wie möglich im Antworttextbereich einfügen, um den/die Entwickler dabei zu unterstützen, herauszufinden, was los ist.

Bevor alle über mich herfallen, weil ich gesagt habe, dass es hier keine richtige oder falsche Antwort gibt, möchte ich kurz erklären, wie ich zu diesem Schluss gekommen bin.

In diesem speziellen Beispiel geht es um eine JSON-Anfrage des OP, die einen anderen Schlüssel als erwartet enthält. Der empfangene Schlüsselname ist zwar aus sprachlicher Sicht sehr ähnlich wie der erwartete Schlüssel, jedoch streng genommen unterschiedlich und wird daher von einer Maschine normalerweise nicht als äquivalent erkannt.

Wie oben erwähnt, hängt die Entscheidung davon ab, was unter Syntax verstanden wird. Wenn die Anfrage mit einem Content-Typ von application/json gesendet wurde, dann ja, die Anfrage ist syntaktisch gültig, da es gültige JSON-Syntax ist, aber nicht semantisch gültig, da es nicht mit dem Erwarteten übereinstimmt (unter der Annahme einer strikten Definition, was die Anfrage semantisch gültig oder ungültig macht).

Wenn die Anfrage andererseits mit einem spezifischeren benutzerdefinierten Content-Typ wie application/vnd.mycorp.mydatatype+json gesendet wurde, der möglicherweise genau festlegt, welche Felder erwartet werden, würde ich sagen, dass die Anfrage leicht syntaktisch ungültig sein könnte, daher die 400-Antwort.

In dem vorliegenden Fall, da der Schlüssel falsch war und nicht der Wert, gab es einen Syntax-Fehler, wenn eine Spezifikation vorhanden war, für gültige Schlüssel. Wenn keine Spezifikation für gültige Schlüssel vorhanden war oder der Fehler beim Wert lag, dann wäre es ein semantischer Fehler.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X