Stellen Sie sich eine API vor, um festzustellen, ob eine Person ihr Geistestier ausgewählt hat. Sie können nur null oder ein Geister-Tier haben.
Zur Zeit:
/person/{id}/selectedSpiritAnimal
Wenn sie ein Tier ausgewählt haben, wird http 200 und zurückgegeben {selectedAnimal:mole}
Wenn sie jedoch keine Auswahl haben, wird http 404 zurückgegeben.
Dies macht mein Geister-Tier unglücklich, da wir ein gültiges Domain-Anliegen - das noch kein Geister-Tier ausgewählt hat - als HTTP-Fehler darstellen.
Außerdem möchten wir als Unternehmen - ähm Sprit-Animal-Hampers-R-us - wissen, wenn jemand keine Auswahl hat, damit wir ihn dazu auffordern können.
Was ist eine bessere Antwort hier:
HTTP 200 und {selectedAnimal:null}
oder noch expliziter
HTTP 200 und {selectedAnimal:null, spiritAnimalSelected: false}
Oder ist es besser, einen 404 zurückzugeben? Da ähnlich wie this image has not yet been uploaded
beim Betrachten eines Bildes online ein 404 this person has not selected a spirit animal
sein würde, könnte ein 404 sein
Diese Frage wurde als Duplikat vorgeschlagen, adressiert jedoch eine ansonsten gültige URL, die angefordert wird, wenn die Anwendung so konfiguriert wurde, dass die von dieser URL dargestellte Änderung nicht zulässig ist.
Während ich hier sehe, wie man eine Ressource darstellt, bei der das Fehlen der Ressource von Bedeutung ist. Dh es ist für den Kunden gültig, die URL anzufordern, und die Antwort lautet, dass Sie die Ressource erfolgreich angefordert haben, die das Fehlen einer Sache darstellt.
Das ist also keine "Geschäftslogik", sondern ein Umstand, in dem das Fehlen einer Sache eine Bedeutung hat (es kann sein, dass viele meiner Kollegen argumentieren, dass 404 immer noch korrekt ist), aber ich bin nicht sicher, wie ich das dem zuordnen soll spez.
Es ist sehr schwierig, eine Antwort zu finden. Ich habe es mir im Laufe des Gesprächs hier und auf der Arbeit mehrmals anders überlegt.
Die Sache, die es für mich hier regelt, ist, dass die Spezifikation sagt, dass ein 4xx ist, wenn der Kunde geirrt hat . In diesem Fall wurde der Client angewiesen, eine Antwort von der URL selectedSpiritAnimal zu erwarten, sodass kein Fehler aufgetreten ist.
Meine Kollegen sind sich einig, dass dies ein Symptom für ein schlechtes API-Design ist
Es ist wahrscheinlich besser, wenn wir einfach / person / {id} anfordern und eine Reihe von Verknüpfungsbeziehungen für die Person zurückgeben nenne es trotzdem dann macht ein 404 sinn. Oder Sie implementieren Teilantworten und lassen / person / {id} ein vollständigeres Dokument zurückgeben, sofern der Client keine Teilmenge der Daten anfordert
Antworten:
HTTP 4xx-Codes sind wahrscheinlich nicht die richtige Wahl für dieses Szenario. Sie geben an, dass es ein gültiger Status ist, Tiere mit null Geistern zu haben, und die API-Route
person/{id}/selectedSpiritAnimal
berücksichtigt, ob eine Person einesid
hat oder nicht.HTTP 4xx-Antworten sind für den Fall reserviert, dass ein Client in der Anforderung etwas Falsches getan hat (siehe Archiv der ursprünglichen Spezifikation von w3 ). Der Kunde macht jedoch eine gültige Anfrage, ob eine Person
id
ein Geistertier hat oder nicht .Daher neige ich zur zweiten Lösung, indem ich einen korrekt formatierten JSON-Body in der Antwort und einen HTTP-2xx-Code verwende.
Wenn Sie nun eine solche Anfrage erhalten und sich herausstellt, dass die Person
id
nicht existiert, ist ein 4xx-Code sinnvoller.quelle
cases in which the client seems to have erred
, andererseits sagt der 404 direktThe server has not found anything matching the Request-URI
. Sie könnten in Betracht ziehen, etwas anzufordern, das keinen Clientfehler enthält. Ich verstehe die Person, die nicht existiert, im Vergleich zu einer nicht existierenden Sub-Requisite, aber das könnte als Antwortnachricht angezeigt werden. 204 scheint ebenfalls relevant zu sein, da die Entität existiert, aber keinen Inhalt für eine Sub-Eigenschaft hat.Lassen Sie mich Ihnen das Richardson Maturity Model vorstellen .
Ihr Problem ist, dass Sie zwei Ressourcen als eine darstellen, wobei Sie eigentlich zwei Ressourcen haben sollten, deren Beziehung durch Hypermedia angegeben ist. Das Verwenden von Hypermedien zur Beschreibung von Beziehungen ist die glorreiche Ebene 3 von Rest.
Ihre Person sollte unter der URI leben
/person/{id}
und das Tier sollte unter der URI leben/spiritanimal/{id}
. Die Person sollte durch einen Link zum Tier angeben, dass sie ein Geistestier hat.Stellen wir uns eine Person namens Bob vor, die die ID 123 und ein Einhorn-Geistertier hat.
GET /person/123
würden zurückkehren;
Jetzt weiß jeder, der Person 123 liest, dass er ein Geistertier hat und die URI hat, unter der er weitere Informationen dazu erhalten kann.
GET /spitiranimal/789
könnte zurückkehren
Stellen wir uns nun eine Person namens Fred vor, die die ID 456 hat und kein Geistertier.
GET /person/456
würden zurückkehren;
Jetzt wird jeder, der Person 456 liest, wissen, dass er kein Geistestier hat, da es keine Verbindung gibt. Es ist nicht erforderlich, einen HTTP-Statuscode zu verwenden, um das Fehlen einer Beziehung darzustellen.
quelle
Dies ist die geeignete URL, um Geistertiere zu bekommen. Daher ist ein 404-Fehler ungeeignet. 404 steht für ein technisches Problem, nicht für ein logisches Problem.
Die geeignete Lösung ist die Rückgabe von http 200 und
{"selectedAnimal": null}
Sie sollen einen haben separaten Webmethod
/person/{id}/hasSelectedSpiritAnimal
die zurückgibt{"isSpiritAnimalSelected": false}
. Hinter den Kulissen kann es vorkommen, dass dieselben Methodenaufrufe ausgeführt werden oder nicht, wobei nur false zurückgegeben wird, wenn null, aber es liegt an der Entscheidung, nicht an dem verbrauchenden Code.Es ist besser zu vermeiden, Abfragen ohne zwingenden Grund zu kombinieren, um sie in eine Webmethode zu unterteilen, selbst wenn die Abfragen eng miteinander verbunden sind.
quelle
When you said "the spirit animal is not currently on file", it seemed quite similar to me to "there is no content"
Kein Inhalt bedeutet kein Inhalt . dh: es gibt "" zurück. Diese beiden sind überhaupt nicht ähnlich. "Das Geistertier ist derzeit nicht in der Akte" unterscheidet sich stark von "".Was Ihr Endpunkt darstellt, ist nicht nur ein Tier. Es ist ein Tier oder ein Mangel daran. Es ist ein Wert, der am besten durch ein
Optional
/Maybe
/Nullable
/ usw. dargestellt wird.So legitime Werte (wie in 200 OK) können sein:
{'animal': <some animal>, 'selected': true}
{'animal': null, 'selected': false}
Ich könnte mir vorstellen, dass die
DELETE
Methode, wenn sie auf den Endpunkt angewendet wird'selected'
,false
erneut festgelegt werden kann, das heißt, das ausgewählte Tier wird nicht festgelegt.Sie können den
'selected'
Schlüssel natürlich hier ablegen, er wird nur zur Verdeutlichung angezeigt. Zeichenfolge vsnull
ist genug für die Unterscheidung.quelle
Sie sollten 404 verwenden.
Da Sie eine Programmierschnittstelle und keine Benutzerschnittstelle erstellen, ist der Text 404 optional.
Ich bevorzuge dies, weil ich Standardprotokolle so oft wie möglich bevorzuge. HTTP hat eine Möglichkeit, Nichtexistenz darzustellen, und das würde ich verwenden.
BEARBEITEN: Angenommen, Sie haben eine Funktion hinzugefügt, mit der Benutzer auswählen können, ob ihre Geistertiere geteilt werden sollen, und jemand hat sie nicht geteilt. Würden Sie 200 OK
null
oder 200 OK zurückgeben"Unauthorized
? Oder würden Sie den Standard 401 Unauthorized / 403 Forbidden verwenden? Dies scheint direkt analog zu sein, als würde man sich überhaupt nicht für eine entscheiden.Wenn Sie alternativ 200 OK + JSON verwenden möchten, sollten Sie zurückkehren
null
.Halte die Dinge sauber. Erstellen Sie nur bei Bedarf weitere Umhüllungen.
quelle
null
(keinen Wert haben). Dies unterscheidet sich davon, dass der Client etwas anfordert, für das kein Steckplatz für den Wert vorhanden ist. Sie würden nicht vorschlagen, einAttributeError
in Python zu werfen, wenn der Wert zufällig istNone
; das würde die Schnittstelle unpraktisch und unnötig schwierig machen, mit zu arbeiten. Noch pragmatischer ist, dass viele HTTP-Client-APIs den 404 in den Standard-Fehlerbehandlungsmechanismus der Sprache (Fehlercode, Ausnahme, Fehlertyp) umwandeln, was bedeutet, dass Sie einen überflüssigen Fehler unterdrücken müssen./person/{id}/selectedSpritAnimal
, beachten Sie die Tippfehler inSprit
)./person/{id}/isSpiritAnimalSelected
verfügbar machen, die dem Client mitteilt, ob eine ausgewählt wurde. Scheint mir das gleiche klassische Beispiel zu sein, bei dem vor dem Lesen geprüft wird, ob eine Datei vorhanden ist. Lesen Sie einfach die Datei und behandeln Sie den ENOENT-Fehler, falls er ausgelöst werden sollte./person/{id}/selectedSpiritAnimal
verwendet werden soll, auch wenn es kein geistiges Tier gibt. Dies bedeutet, dass HTTP 4xx in einem solchen Fall nicht korrekt ist. Op gibt auch korrekt an, dass dies ein Geruch von schlechtem API-Design sein kann.