wake-up-neo.com

HTTP 400 (ungültige Anforderung) für logischen Fehler, keine fehlerhafte Anforderungssyntax

Die HTTP/1.1-Spezifikation (RFC 2616) hat folgende Bedeutung zur Bedeutung von Statuscode 400, Bad Request (§10.4.1) :

Die Anfrage konnte von .__ nicht verstanden werden. der Server wegen fehlerhafter Syntax . Der Client SOLLTE NICHT das .__ wiederholen. Anfrage ohne Änderungen.

Heutzutage scheint es unter einigen HTTP-basierten APIs allgemein üblich zu sein, 400 zu verwenden, um einen logischen anstelle eines syntax -Fehlers bei einer Anforderung zu bedeuten. Meine Vermutung ist, dass APIs dies tun, um zwischen 400 (Client-induziert) und 500 (Server-induziert) zu unterscheiden. Ist es akzeptabel oder falsch, 400 zu verwenden, um nicht-syntaktische Fehler anzuzeigen? Wenn es akzeptabel ist, gibt es auf RFC 2616 eine kommentierte Referenz, die mehr Einblick in die beabsichtigte Verwendung von 400 bietet?

Beispiele:

60
Atif Aziz

Ab diesem Zeitpunkt enthält der neueste Entwurf der HTTPbis - Spezifikation, der RFC 2616 ersetzen und obsolet werden soll, den Status :

Der Statuscode 400 (Bad Request) gibt an, dass der Server nicht oder verarbeitet die Anforderung nicht, da die empfangene Syntax ungültig ist unsinnig oder überschreitet eine gewisse Einschränkung dessen, was der Server will herstellen.

Diese Definition, auch wenn sie natürlich noch Änderungen unterliegt, bestätigt die weit verbreitete Praxis, auf logische Fehler mit einer 400 zu reagieren.

14
Jon

Status 422 ( RFC 4918, Abschnitt 11.2 ) fällt in den Sinn:

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 ist korrekt (also 400 (Bad Request) ) Statuscode ist ungeeignet), konnte jedoch die enthaltenen Anweisungen nicht verarbeiten. Diese Fehlerbedingung kann beispielsweise auftreten, wenn ein XML-Anforderungshauptteil wohlgeformte (d. H. Syntaktisch korrekte), aber semantisch fehlerhafte XML-Anweisungen enthält.

60
Julian Reschke

HTTPbis wird die Formulierung von 400 Bad Request so behandeln, dass auch logische Fehler abgedeckt werden. 400 werden also 422 aufnehmen.

Von https://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-18#section-7.4.1
"Der Server kann oder kann die Anfrage aufgrund eines Clientfehlers (z. B. fehlerhafte Syntax) nicht verarbeiten."

6
Andrei Neculau

Obwohl ich 400 verwendet habe, um auch logische Fehler darzustellen, muss ich sagen, dass die Rückgabe von 400 in diesem Fall aufgrund der Art, wie die Spezifikation liest, falsch ist. Ich denke also, der logische Fehler könnte darin bestehen, dass eine Beziehung zu einer anderen Entität fehlgeschlagen ist oder nicht erfüllt wurde und dass Änderungen an der anderen Entität dazu führen könnten, dass die gleiche Entität später passiert. Wie der Versuch, einen Mitarbeiter (vollständig hypothetisch) als Mitglied einer Abteilung hinzuzufügen, wenn dieser Mitarbeiter nicht existiert (logischer Fehler). Das Hinzufügen eines Mitarbeiters als Mitgliederanforderung kann fehlschlagen, da der Mitarbeiter nicht vorhanden ist. Die gleiche genaue Anforderung könnte jedoch bestehen, nachdem der Mitarbeiter zum System hinzugefügt wurde.

Nur meine 2 Cent ... Wir brauchen Anwälte und Richter, um die Sprache heutzutage im RFC zu interpretieren :)

Vielen Dank. Vish

2
Vish

Es könnte argumentiert werden, dass falsche Daten in Ihrer Anfrage ein Syntaxfehler sind, auch wenn Ihre tatsächliche Anfrage auf HTTP-Ebene (Anfragezeile, Header usw.) syntaktisch gültig ist.

Wenn beispielsweise ein Restful-Webdienst als akzeptierte POSTs mit einem benutzerdefinierten XML-Inhaltstyp application/vnd.example.com.widget+xml dokumentiert ist und Sie stattdessen etwas Klatschtext oder eine Binärdatei senden, scheint es verständlich, dass dies als Syntaxfehler behandelt wird nicht in der erwarteten Form.

Ich kenne zwar keine offiziellen Hinweise, um dies zu untermauern, wie üblich scheint es nur die Interpretation von RFC 2616 zu sein.

Update: Den überarbeiteten Wortlaut in RFC 7231 §6.5.1 beachten:

Der Statuscode 400 (Bad Request) gibt an, dass der Server die Anfrage aufgrund eines als Clientfehler empfundenen Problems nicht verarbeiten kann oder wird (beispielsweise fehlerhafte Anforderungssyntax, ungültiges Anforderungsnachrichten-Framing oder irreführendes Anforderungsrouting).

scheint dieses Argument mehr zu stützen als das jetzt veraltete RFC 2616 §10.4.1 , in dem nur gesagt wurde:

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

2
Day

Auf Java EE-Servern wird ein 400 zurückgegeben, wenn Ihre URL auf eine nicht vorhandene "Web-Anwendung" verweist. Ist das ein "Syntaxfehler"? Kommt drauf an, was Sie unter Syntaxfehler verstehen. Ich würde Ja sagen.

Im Englischen schreiben Syntaxregeln bestimmte Beziehungen zwischen Wortteilen vor. Zum Beispiel ist "Bob Maries Mary" syntaktisch korrekt, weil es dem Muster {Noun + Verb + Noun} folgt. Während "Bob Marriage Mary" wäre syntaktisch falsch, {Noun + Noun + Noun}.

Die Syntax einer einfachen URL lautet {Protokoll +: + // + Server +: + Port}. Demnach ist " http://www.google.com:80 " syntaktisch korrekt. 

Aber was ist mit "abc: //www.google.com: 80"? Es scheint genau dem gleichen Muster zu folgen. Aber wirklichit ist ein Syntaxfehler. Warum? Weil 'abc' kein DEFINED-Protokoll ist.

Der Punkt ist, dass die Feststellung, ob wir eine 400-Situation haben oder nicht, mehr erfordert, als die Zeichen, Leerzeichen und Trennzeichen zu analysieren. Es muss auch erkennen, was die gültigen "Teile der Sprache" sind.

1
Panu Logic

Das ist schwierig.

Ich denke wir sollten;

  1. 4xx-Fehler werden nur zurückgegeben, wenn der Client berechtigt ist, Änderungen an der Anforderung, den Headern oder dem Text vorzunehmen, die dazu führen, dass die Anforderung mit derselben Absicht erfolgreich ist.

  2. Gibt Fehlerbereichscodes zurück, wenn die erwartete Mutation nicht aufgetreten ist, d. H. Ein DELETE nicht aufgetreten ist oder ein PUT nichts geändert hat. Ein POST ist jedoch interessanter, da die Spezifikation besagt, dass es verwendet werden sollte, um Ressourcen an einem neuen Speicherort zu erstellen oder nur eine Nutzlast zu verarbeiten.

Anhand des Beispiels in Vishs Antwort wird ein Anwendungsfehler gemeldet, wenn die Anfrage die Absicht hat, Mitarbeiterin Priya zu einer Abteilung Marketing hinzuzufügen, Priya jedoch nicht gefunden wurde oder ihr Konto archiviert ist.

Die Anfrage hat gut geklappt, sie hat Ihren Bewerbungsregeln entsprochen, der Kunde hat alles richtig gemacht, die ETags sind aufeinander abgestimmt usw. usw.

Da wir HTTP verwenden, müssen wir basierend auf der Auswirkung der Anforderung auf den Status der Ressource antworten. Und das hängt von Ihrem API-Design ab.

Vielleicht haben Sie das entworfen.

PUT { updated members list } /marketing/members

Das Zurückgeben eines Erfolgscodes würde anzeigen, dass der "Ersatz" der Ressource funktioniert hat. Ein GET für die Ressource würde Ihre Änderungen widerspiegeln, aber nicht.

Nun müssen Sie einen geeigneten negativen HTTP-Code auswählen, und das ist der schwierige Teil, da die Codes stark für das HTTP-Protokoll und nicht für Ihre Anwendung bestimmt sind.

Wenn ich die offiziellen HTTP-Codes lese, sehen diese beiden passend aus.

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.

Und

Der Statuscode 500 (Interner Serverfehler) zeigt an, dass der Server auf einen unerwarteten Zustand gestoßen ist, der ihn daran gehindert hat, die Anforderung zu erfüllen.

Obwohl wir die 500 traditionell als eine unbehandelte Ausnahme angesehen haben: - /

Ich halte es nicht für unangemessen, einen eigenen Statuscode zu erfinden, solange er konsequent angewendet und entworfen wird.

Dieses Design ist einfacher zu handhaben.

PUT { membership add command } /accounts/groups/memberships/instructions/1739119

Dann können Sie Ihre API so gestalten, dass die Anweisung immer erfolgreich erstellt wird. Sie gibt 201 Created und einen Location -Header zurück, und alle Probleme mit der Anweisung werden in dieser neuen Ressource gespeichert.

A POST ist eher wie das letzte PUT an einen neuen Ort. A POST ermöglicht jede Art von Serververarbeitung einer Nachricht, wodurch Designs geöffnet werden, die besagen, dass so etwas wie "Die Aktion ist erfolgreich fehlgeschlagen."

Wahrscheinlich haben Sie bereits eine API geschrieben, die dies tut, eine Website. Sie POST das Zahlungsformular und es wurde erfolgreich abgelehnt, weil die Kreditkartennummer falsch war.

Ob Sie bei einem POST 200 oder 201 zusammen mit Ihrer Ablehnungsnachricht zurückgeben, hängt davon ab, ob eine neue Ressource erstellt wurde und an einem anderen Speicherort für GET verfügbar ist oder nicht.

Wenn das alles gesagt ist, würde ich gerne APIs entwerfen, die weniger PUTs benötigen, vielleicht nur Datenfelder aktualisieren, und Aktionen und Dinge, die Regeln und Verarbeitung aufrufen oder nur ein höheres Risiko für erwartete Fehler aufweisen, können so entworfen werden, dass sie POST ein Anweisungsformular.

1
Luke Puplett