545 Stimmen

Was ist der richtige REST-Antwortcode für eine gültige Anfrage, aber leere Daten?

Sie führen zum Beispiel eine GET-Anfrage für users/9 aber es gibt keinen Benutzer mit der ID #9. Welches ist der beste Antwortcode?

  • 200 OK
  • 202 Angenommen
  • 204 Ohne Inhalt
  • 400 Schlechte Anfrage
  • 404 nicht gefunden

20voto

Bluebox Punkte 363

Es werden zwei Fragen gestellt. Eine im Titel und eine im Beispiel. Ich denke, dies hat teilweise zu dem Streit darüber geführt, welche Antwort angemessen ist.

Im Titel der Frage wird nach leeren Daten gefragt. Leere Daten sind immer noch Daten, aber sie sind nicht dasselbe wie keine Daten. Dies legt also nahe, eine Ergebnismenge anzufordern, d. h. eine Liste, vielleicht von /users . Wenn eine Liste leer ist, handelt es sich immer noch um eine Liste, daher ist eine 204 (ohne Inhalt) am besten geeignet. Sie haben gerade nach einer Liste von Benutzern gefragt und eine erhalten, die zufällig keinen Inhalt hat.

Das Beispiel fragt stattdessen nach einem bestimmten Objekt, einem Benutzer, /users/9 . Wenn der Benutzer #9 nicht gefunden wird, wird kein Benutzerobjekt zurückgegeben. Sie haben nach einer bestimmten Ressource (einem Benutzerobjekt) gefragt und diese nicht erhalten, weil sie nicht gefunden wurde, daher ist ein 404 angemessen.

Ich denke, die Art und Weise zu arbeiten ist, wenn Sie die Antwort in der Art und Weise, die Sie erwarten, ohne Hinzufügen einer bedingten Anweisung verwenden können, dann verwenden Sie eine 204 sonst eine 404.

In meinen Beispielen kann ich über eine leere Liste iterieren, ohne zu prüfen, ob sie Inhalt hat, aber ich kann keine Benutzerobjektdaten auf einem Null-Objekt anzeigen, ohne etwas zu brechen oder eine Prüfung hinzuzufügen, um zu sehen, ob es null ist.

Sie könnten natürlich ein Objekt mit dem Null-Objekt-Muster zurückgeben, wenn das Ihren Bedürfnissen entspricht, aber das ist eine Diskussion für ein anderes Thema.

17voto

Ashish Singh Punkte 181

Zusammenfassen oder vereinfachen,

2xx: Optionale Daten: Wohlgeformter URI: Kriterium ist nicht Teil des URI: Wenn das Kriterium optional ist und in @RequestBody und @RequestParam angegeben werden kann, sollte dies zu 2xx führen. Beispiel: Filter nach Name / Status

4xx: Erwartete Daten : Nicht wohlgeformter URI : Kriterium ist Teil des URI : Wenn das Kriterium obligatorisch ist und nur in @PathVariable angegeben werden kann, sollte es zu 4xx führen. Beispiel: Abfrage nach eindeutiger ID.

Also für die angefragte Situation: "users/9" würde 4xx (möglicherweise 404) sein. Aber für "users?name=superman" sollte 2xx sein (möglicherweise 204)

16voto

Christian Hujer Punkte 15510

Was in den vorhandenen Antworten nicht näher erläutert wird, ist, dass es einen Unterschied macht, ob Sie Pfadparameter oder Abfrageparameter verwenden.

  • Im Falle von Pfadparametern ist der Parameter Teil des Ressourcenpfads. Im Falle von /users/9 sollte die Antwort lauten 404 weil diese Ressource nicht gefunden wurde. /users/9 ist die Ressource, und das Ergebnis ist unär oder ein Fehler, sie existiert nicht. Dies ist pas eine Monade.
  • Im Falle von Abfrageparametern ist der Parameter nicht Teil des Ressourcenpfads. Im Falle von /users?id=9 sollte die Antwort lauten 204 weil die Ressource /users wurde gefunden, konnte aber keine Daten zurückgeben. Die Ressource /users existiert und das Ergebnis n-är ist, existiert es auch, wenn es leer ist. Wenn id einzigartig ist, ist diese es eine Monade.

Ob Pfadparameter oder Abfrageparameter verwendet werden, hängt vom Anwendungsfall ab. Ich bevorzuge Pfadparameter für obligatorische, normative oder identifizierende Argumente und Abfrageparameter für optionale, nicht-normative oder attributive Argumente (wie Paging, Kollationierung, Gebietsschema und so weiter). In einer REST-API würde ich verwenden /users/9 pas /users?id=9 insbesondere wegen der möglichen Verschachtelung, um "untergeordnete Datensätze" zu erhalten wie /users/9/ssh-keys/0 um den ersten öffentlichen ssh-Schlüssel zu erhalten oder /users/9/address/2 um die dritte Postanschrift zu erhalten.

Ich ziehe es vor, 404 zu verwenden. Hier ist der Grund dafür:

  • Die Aufrufe für unäre (1 Ergebnis) und n-äre (n Ergebnisse) Methoden sollten sich nicht grundlos unterscheiden. Ich möchte nach Möglichkeit die gleichen Antwortcodes haben. Die Anzahl der erwarteten Ergebnisse ist natürlich ein Unterschied, sagen wir, Sie erwarten, dass der Körper ein Objekt (unär) oder ein Array von Objekten (n-är) ist.
  • Für n-ary würde ich ein Array zurückgeben, und falls es keine Ergebnisse gibt, würde ich nicht keine Menge (kein Dokument) zurückgeben, sondern eine leere Menge (leeres Dokument, wie leeres Array in JSON oder leeres Element in XML). Das heißt, es ist immer noch 200, aber mit null Datensätzen. Es gibt keinen Grund, diese Information anders als im Textkörper auf die Leitung zu setzen.
  • 204 ist wie ein void Methode. Ich würde sie nicht verwenden für GET nur für POST , PUT und DELETE . Ich mache eine Ausnahme im Fall von GET wobei die Bezeichner Abfrageparameter und nicht Pfadparameter sind.
  • Den Datensatz nicht zu finden ist wie NoSuchElementException , ArrayIndexOutOfBoundsException oder etwas Ähnliches, weil der Client eine ID verwendet, die nicht existiert.
  • Aus der Sicht des Codes ist es wichtig, die 204 bedeutet eine zusätzliche Verzweigung im Code, die vermieden werden könnte. Es verkompliziert den Client-Code und in einigen Fällen auch den Server-Code (je nachdem, ob Sie Entity/Model-Monaden oder einfache Entities/Models verwenden; und ich stark empfehlen Aufenthalt weg von Entität/Modell Monaden, es kann zu bösen Bugs führen, wo wegen der Monade Sie denken, eine Operation erfolgreich ist und 200 oder 204 zurückgeben, wenn Sie tatsächlich etwas anderes zurückgegeben haben sollte).
  • Client-Code ist einfacher zu schreiben und zu verstehen, wenn 2xx bedeutet, dass der Server das getan hat, was der Client angefordert hat, und 4xx bedeutet, dass der Server nicht das getan hat, was der Client angefordert hat, und dass es die Schuld des Clients ist. Dem Client nicht den Datensatz zu geben, den der Client nach der id angefordert hat, ist der Fehler des Clients, weil der Client eine id angefordert hat, die nicht existiert.

Und nicht zuletzt: Konsistenz

  • GET /users/9
  • PUT /users/9 y DELETE /users/9

PUT /users/9 y DELETE /users/9 müssen bereits zurückkehren 204 im Falle einer erfolgreichen Aktualisierung oder Löschung. Was sollten sie also zurückgeben, wenn der Benutzer 9 nicht existiert? Es macht keinen Sinn, wenn dieselbe Situation je nach der verwendeten HTTP-Methode mit unterschiedlichen Statuscodes dargestellt wird.

Außerdem gibt es keinen normativen, sondern einen kulturellen Grund: Wenn 204 wird verwendet für GET /users/9 Das nächste, was bei dem Projekt passieren wird, ist, dass jemand denkt, dass die 204 ist gut für n-äre Methoden. Und das verkompliziert den Client-Code, denn anstatt einfach zu prüfen, ob 2xx und die Dekodierung des Textes, muss der Client nun speziell prüfen, ob 204 und überspringen Sie in diesem Fall die Dekodierung des Körpers. Was macht der Client stattdessen? Ein leeres Array erstellen? Warum wird das dann nicht auf der Leitung übertragen? Wenn der Client das leere Array erstellt, ist 204 eine Form von dummer Kompression. Verwendet der Client null Stattdessen wird eine ganz andere Dose Würmer geöffnet.

14voto

Priyantha Punkte 4231

Según w3 Posten,

200 OK

Die Anfrage war erfolgreich. Die Informationen, die mit der Antwort zurückgegeben werden, hängen von der in der Anfrage verwendeten Methode ab

202 Angenommen

Der Antrag wurde zur Bearbeitung angenommen, aber die Bearbeitung ist noch nicht abgeschlossen.

204 Ohne Inhalt

Der Server hat die Anfrage erfüllt, muss aber keinen Entity-Body zurückgeben, sondern kann aktualisierte Metainformationen zurückgeben.

400 Schlechte Anfrage

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

401 Unerlaubt

Die Anfrage erfordert eine Benutzerauthentifizierung. Die Antwort MUSS ein WWW-Authenticate-Header-Feld enthalten

404 nicht gefunden

Der Server hat nichts gefunden, was der Request-URI entspricht. Es wird nicht angegeben, ob der Zustand vorübergehend oder dauerhaft ist

13voto

Darko Maksimovic Punkte 1017

Es ist traurig, dass etwas so Einfaches und gut Definiertes in diesem Thread zur "Meinungsgrundlage" wurde.

Ein HTTP-Server kennt nur "Entitäten", was eine Abstraktion für jeden Inhalt ist, sei es eine statische Webseite, eine Liste von Suchergebnissen, eine Liste von anderen Entitäten, eine json-Beschreibung von etwas, eine Mediendatei, usw. usw.

Jede solche Einheit sollte durch eine eindeutige URL identifizierbar sein, z. B.

  • /user/9 -- eine einzelne Entität: ein USER ID=9
  • /users -- eine einzige Einheit: eine LISTE aller Benutzer
  • /media/x.mp3 -- eine einzelne Einheit: eine Mediendatei namens x.mp3
  • /search -- eine einzige Einheit: ein dynamischer INHALT auf der Grundlage von Abfrageparametern

Wenn ein Server eine Ressource unter der angegebenen URL findet, spielt es keine Rolle, was seine Inhalt are -- 2G Daten, null, {}, [] -- Solange es existiert, wird es 200 sein. Ist eine solche Entität dem Server jedoch nicht bekannt, wird ERWARTET, dass er 404 "Not Found" zurückgibt.

Eine Verwirrung scheint von Entwicklern auszugehen, die meinen, wenn die Anwendung einen Handler für eine bestimmte Pfadform hat, sollte dies kein Fehler sein. In den Augen des HTTP-Protokolls spielt es keine Rolle, was in den Interna des Servers passiert ist (d.h. ob der Standard-Router geantwortet hat oder ein Handler für eine bestimmte Pfadform), solange es auf dem Server keine passende Entität zur angeforderten URL gibt (die angeforderte MP3-Datei, Webseite, Benutzerobjekt usw.), die einen gültigen Inhalt (leer oder anders) zurückgeben würde, muss es 404 (oder 410 usw.) heißen.

Ein weiterer Punkt, der für Verwirrung sorgt, sind die Begriffe "keine Daten" und "keine Einheit". Bei ersterem geht es um den Inhalt einer Entität, bei letzterem um ihre Existenz.

Beispiel 1:

  • Keine Angaben: /users gibt 200 OK, body: [] zurück, da noch niemand registriert ist
  • Keine Entität: /users gibt 404 zurück, weil es keinen Pfad /users gibt

Beispiel 2:

  • Keine Angaben: /user/9 gibt 200 OK zurück, body: {}, da Benutzer ID=9 seine/ihre persönlichen Daten nicht eingegeben hat
  • Keine Entität: /user/9 gibt 404 zurück, weil es keinen Benutzer ID=9 gibt

Beispiel 3:

  • Keine Angaben: /search?name=Joe gibt 200 OK [] zurück, weil es keine Joes in der DB gibt
  • Keine Entität: /search?name=Joe gibt 404 zurück, weil es keinen Pfad /search gibt

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