Sollte "Keine Ergebnisse" ein Fehler in einer RESTful-Antwort sein?

52

Ich beschreibe ein Beispiel:
Ich beginne, eine API für eine Bäckerei zu erstellen. Mit der API können Benutzer ihren Katalog nach Backwaren durchsuchen, beispielsweise nach hausgemachten Minz-Schokoladenkeksen api.examplebakery.com/search?q=......

Jemand sucht auf diese Weise nach einem Produkt mit dem Namen pineapple-banana flavoured cookiesund findet offensichtlich keine Ergebnisse.

Sollte dies als Fehler zurückgegeben werden? Die Suche ist nicht fehlgeschlagen, die API hat gesucht und erfolgreich festgestellt, dass keine Cookies gefunden wurden. Die API sollte nicht zurückgegeben werden 404, da die API tatsächlich gefunden wurde.

Berry M.
quelle
51
204 Kein Inhalt
AakashM 28.09.17
3
@gnat: Dies ist kein Duplikat, da es sich bei der anderen Frage um eine bestimmte Ressource handelt und nicht um eine Abfrage für mehrere Ressourcen.
Greg Burghardt
7
Angenommen, Sie haben eine Funktion, die ein Array von Objekten zurückgibt. Wenn es keine Objekte gibt, die einem bestimmten Anwendungsfall entsprechen, möchten Sie die Funktion lieber über eine Ausnahme ausführen oder ein leeres Array zurückgeben?
Kevin - Reinstate Monica
2
@AakashM Es ist ziemlich ungewöhnlich, HTTP-204 auf eine GET-Anfrage zurückzuführen. Ich weiß, dass ich das nirgendwo gesehen habe. Soweit ich weiß, wird HTTP-204 normalerweise als Antwort verwendet, wenn eine Ressource auf dem Server geändert wird, z. B. POST / PUT / DELETE-Anforderungen.
Radu Murzea

Antworten:

122

Wenn Ergebnisse vorliegen, handelt es sich bei der Ausgabe um eine Liste (JSON, basierend auf Ihrem Kommentar). Bei Abfragen ohne Ergebnisse sollte die Ausgabe genau gleich sein. Die Liste simple enthält 0 Elemente.

Wenn Ihre Antwort normalerweise so lautet:

{
    "results": [
        {
            "name": "Pancakes",
            ....
        },
        {
            "name": "French Fries",
            ....
        }
    ]
}

Dann sollte es für eine Abfrage mit 0 Ergebnissen sein:

{
    "results": []
}

Wenn Sie auch Metadaten dazu hinzufügen, wie viele "Seiten" der Ergebnisse vorhanden sind, Links zu diesen "Seiten" usw., dann würde ich vorschlagen, dass 1 "Seite" vorhanden ist.

Der HTTP-Status sollte derselbe sein wie bei Ergebnissen - 200 OK.

204 No Contentscheint auch eine Option zu sein, liegt aber nicht daran, dass Sie tatsächlich "Inhalt" - die leere Liste - zurückgeben. Wenn Sie der Meinung sind, dass eine leere Liste nicht als "Inhalt" gilt, ändern Sie dann die Antwort, um Vorschläge für die Rechtschreibung anzubieten? Der Kern der Antwort wird immer noch eine leere Liste sein, aber jetzt gibt es noch mehr "Inhalt".

Für weitere nützliche Informationen zu HTTP-Statuscodes ist jpmc26 ihre Antwort lesenswert.

Jory Geerts
quelle
9
Dies ist die gleiche Art des Denkens wie das Nullobjektmuster . Fehler und Null sind nicht die einzige Möglichkeit, um zu sagen, dass es hier nichts gibt. Manchmal möchten Sie Ihr Nichts leise ausdrücken. Auf diese Weise müssen Kunden nicht umsonst testen.
candied_orange
54
Ich würde argumentieren, dass die Rückgabe eines 204 unangemessen ist, da Sie Inhalte zurückgeben. Es ist nur so, dass der Inhalt keine Ergebnisse hat, was sich davon unterscheidet, dass überhaupt kein Inhalt zurückgegeben wird.
TMN
9
@TMN vereinbart - 204 ist nicht geeignet für "keine Ergebnisse". Ihre Abfrage sollte immer ein Array mit den Ergebnissen innerhalb des Arrays zurückgeben. Wenn es keine Ergebnisse gibt, wird der Client das natürlich behandeln. Wenn der Kunde einen speziellen Text anzeigen möchte ("Es wurden keine Ergebnisse gefunden"), ist das in Ordnung. 204 sollte nur für einen Endpunkt zurückgegeben werden, der natürlich kein Ergebnis zurückgibt.
JasonB
1
Sie könnten 204 verwenden, wenn Sie null serialisiert als eine leere Zeichenfolge zurückgeben, die ich zurückerhalte
Ewan
15
Diese. Das Wichtigste beim Erstellen einer RESTful-API ist der API-Teil, nicht die Restfullness. Eine gute API erleichtert Kunden / Verbrauchern das Leben. Ein leeres Array ist einfacher zu handhaben als Nullwerte / Ausnahmen / Statuscodes.
Guran
37

Wenn Sie sich für einen HTTP-Code entscheiden, sollten Sie immer diese Frage stellen:

Was kann / wird / soll ein beliebiger Kunde mit der Antwort tun?

  1. Sollte der Kunde immer die Antwort als einen Fehler behandeln? Dann möchten Sie 4xx oder 5xx, je nachdem, ob das Problem die Eingabe des Clients oder die Prozesse des Servers sind.
  2. Sollte der Kunde stattdessen eine Anfrage an einen anderen Ort stellen? Dann ist 3xx genau das Richtige für Sie.
  3. Hat der Server das getan, worum der Client gebeten hat (erfolgreich)? Das ist 2xx.

Entscheiden Sie immer, in welchem ​​Bereich sich Ihr Antwortcode zuerst befinden soll. Wenn Sie so schnell vorgehen, werden viele Antwortcodes als Optionen eliminiert, und (was vielleicht noch wichtiger ist) das Befolgen der Semantik der Codes wird viel einfacher. In den Anfangsabschnitten der HTTP-Codedokumentation finden Sie Erläuterungen zu den einzelnen Codekategorien.

In diesem Fall hat der Client eine Liste der Ergebnisse angefordert, denen ein Filter von einem gültigen, vorhandenen Endpunkt zugewiesen wurde, und er hat die Berechtigung, darauf zuzugreifen. Der Server konnte die Anforderung verarbeiten und die entsprechenden zurückzugebenden Daten (keine Elemente) ermitteln, sodass die Anforderung erfolgreich war. Es passiert einfach, dass der Filter, den sie gaben, alle Ergebnisse herausfilterte . Es ist nicht Sache des Servers, zu bestimmen, ob der Client dies wünscht oder nicht, da dies für einige Clients ein erwartetes Ergebnis sein kann. Wenn es sich um ein Problem mit dem Client-Code handelt, liegt es in der Verantwortung des Clients, dies zu ermitteln, zu überprüfen und entsprechend zu behandeln. Das ist also eindeutig 2xx.

Nun lautet die Frage: "Welche 2xx?" Dies hängt davon ab, wie der Server reagieren soll.

  • Senden Sie eine Darstellung einer leeren Liste zurück, wie in einigen anderen Antworten beschrieben? Wenn dies der Fall ist, möchten Sie 200. 200 bedeutet, dass auf dem Server keine Probleme aufgetreten sind und eine Darstellung der Ergebnisse vorliegt, die der Client verwenden kann. Dies ist wahrscheinlich die bequemste Methode, um auf Ihre Kunden zu reagieren. Sie können die Antwort nur analysieren, ob Ergebnisse vorliegen oder nicht, und dann selbst herausfinden, wie mit einer leeren Liste umgegangen werden soll.
  • 204 ist hier nicht semantisch falsch, aber Sie müssten mit keinem Nachrichtentext antworten . Dies bedeutet, dass jeder Client-Code explizit nach verschiedenen HTTP-Codes suchen (oder zumindest nach dem Fehlen eines Nachrichtentexts) und diese separat behandeln muss. Es ist unbequem und führt eher zu schlecht benommenen Kunden.

Die anderen sind überhaupt nicht anwendbar:

  • 201 kommt nicht in frage. Sie haben keine persistenten Ressourcen erstellt und geben keinen Speicherort an eine erstellte Ressource zurück.
  • 202 kommt nicht in frage. Die Anfrage ist erledigt; Es wird nicht im Hintergrund verarbeitet.
  • 203 bedeutet, dass die Antwort zwischen dem autorisierenden Server und dem Client geändert wurde. Ihre RESTful-Schnittstelle ist der autorisierende Server, daher gilt dies hier nicht.
  • 205 ergibt keinen Sinn. Der Client muss nichts löschen oder aktualisieren.
  • 206 scheint für die Rückgabe einer großen Ressource über mehrere Antworten ausgelegt zu sein. Es erfordert auch , dass der Kunde fragen , für einen Teil des Inhalts in den Headern (so Paginierung über Query - Strings nicht qualifiziert). Gilt hier nicht.

Es sollte also entweder 200 oder 204 sein, und 200 führt mit größerer Wahrscheinlichkeit zu einfacherem, robusterem Clientcode (insbesondere, wenn Sie eine konsistente Antwortstruktur mit einer leeren Liste verwenden).

jpmc26
quelle
5
Würde mich für die Meinung des Downvoters interessieren. Ich halte nichts von alledem für kontrovers.
jpmc26
2
Ich glaube nicht, dass Kunden explizit nach 204 suchen müssen. Alles, was sie brauchen, ist die Fähigkeit, ein Null-Antwort-Objekt zu handhaben. Es ist die Aufgabe des HTTP-Frameworks, 204 durch Überspringen des Teils "parse the body" zu behandeln. 200 mit Content-Länge 4 und body null ist genauso.
Agent_L
1
@Agent_L Sie haben Recht, wenn der Server mit einer Struktur antwortet, die nicht mit der normalen Antwort übereinstimmt (wie z. B. das Platzieren nulleiner Liste), können Sie die Vorteile der Konsistenz auch mit 200 nicht nutzen. Ich beschreibe jedoch die Verwendung von a Antwort, die mit der normalen Struktur übereinstimmt und eine leere Liste enthält, in die die Liste der Ergebnisse normalerweise passt. 204 nimmt jede Gelegenheit, um eine solche konsistente Antwort zu haben. Auch in HTTP-Client-Bibliotheken, die über praktische Funktionen verfügen, müssen Sie häufig (normalerweise?) Einen expliziten Aufruf zum Parsen von JSON ausführen.
jpmc26
@Agent_L Insbesondere bei Listen können Anrufer ihren Code häufig einfach über eine leere Liste laufen lassen (z. B. durch Schleifen), während sie eine explizite Prüfung benötigen, um eine andere Art der Darstellung zu handhaben.
jpmc26
16

Nein. Die Verwendung von 404, um anzuzeigen, dass Ihre Anfrage verarbeitet wurde, aber keine Übereinstimmungen gefunden wurden, ist schrecklich, weil:

  • Bedingter Ablauf basierend auf Ausnahmebehandlung (dh Erzwingen eines nicht außergewöhnlichen Ergebnisses, um eine Ausnahme im Client zu erstellen und zu behandeln, die nicht performant und umständlich sein kann)

  • Mehrdeutigkeit zwischen "realer" Seite nicht gefunden, Sie haben den Endpunkt falsch eingegeben

Beachten Sie, dass es immer einen Client gibt, der die Nachricht deserialisiert, und es ist wichtig, was dieser Client zurückgibt. nicht die serialisierung.

Wenn der Client null zurückgeben soll, verwenden Sie die Serialisierung von null. Wenn der Client ein leeres Array zurückgeben soll, verwenden Sie []. Wenn der Client einen Fehler auslösen soll, verwenden Sie 500 und übergeben Sie die Fehlermeldung

Ewan
quelle
2
Warum sollte der Server darauf achten, was der Client mit den Informationen tut? (PS: Ich bin nicht derjenige, der deine Antwort abgelehnt hat).
Radu Murzea
In diesem Zusammenhang ist der "Client" der Code, der auf dem Client-Gerät ausgeführt wird und den Dienst für die Client-Anwendung verfügbar macht. Es muss in der Lage sein, die Dienstmethoden verfügbar zu machen und die vom Dienst beabsichtigten Ergebnisse zurückzugeben. Sie benötigen ein Client-Server-Paar, damit die Kommunikation überhaupt funktioniert
Ewan
3
Verwenden Sie 5xx natürlich nicht für Client- Fehler. Bevorzugen Sie in diesem Fall 4xx.
Kevin
1
Sollte es in den meisten Fällen nicht "Server", nicht "Client" sein? Es ist der Server, der die Anfrage bearbeitet und eine Antwort liefert. Verarbeitet der Client nur die Antwort? In welchem ​​Fall wäre ein 5xx-Code OK, da es sich um einen Serverfehler handelt, nicht um einen Clientfehler?
MrWhite
2
Das Problem mit allen Fehlercodes ist, dass sie innerhalb von http eine Bedeutung haben. 500 ist der einzige Code, der geeignet ist, wenn Ihr Dienst eine Ausnahme
auslöst
9

Beyond @ Ewans sehr gute Antwort:

Wenn es sich bei der Abfrage um eine Art Abfrage handelt, die eine Reihe von Ergebnissen zurückgibt, ist die leere Reihe logisch genauso geeignet wie eine Reihe von einer oder mehreren. Im Allgemeinen ist es aus den Gründen, die @Ewan angibt, mehr schädlich als nützlich, die leere Menge in einen Fehler umzuwandeln, und es ist einfach unnötig.

Wenn es sich bei der Abfrage um eine Art Abfrage handelt, die nach einem bestimmten Singleton sucht und diesen zurückgibt (von dem erwartet wird, dass er gefunden wird, z. B. exakte Übereinstimmung mit der ID), ist "Nicht gefunden" eine logisch angemessene mögliche Antwort.

Erik Eidt
quelle
Ja, ich dachte genau das auf Ewans Antwort.
Walfrat
5

Sie gehen davon aus, dass der Code eine spezielle Aktion ausführen muss, wenn keine Daten zurückgegeben werden. Dies ist jedoch möglicherweise nicht der Fall. Der Code sucht einfach nach einer Produktanzahl oder hängt die Ergebnisse an eine Liste oder eine beliebige Anzahl von Dingen an. Sie sollten einem Benutzer nur dann einen "Fehler" melden, wenn tatsächlich ein Fehler vorliegt.

John Smith
quelle
3
Msgstr "Sie sollten einem Benutzer nur dann einen" Fehler "melden, wenn tatsächlich ein Fehler vorliegt." - diese. Eine leere Ergebnismenge bei einer "Suche" ist normalerweise kein "Fehler". Wenn jedoch die Datenbankverbindung fehlschlug, was bedeutete, dass die Suche tatsächlich nicht durchgeführt werden konnte, wäre eine leere Ergebnismenge (und kein Fehler) andernfalls mehrdeutig. In diesem Fall wäre eine Art Fehlerstatus angemessen (möglicherweise zusammen mit einer leeren Ergebnismenge - abhängig von der Definition der API).
MrWhite
0

Wenn ich eine API verwende, muss ich als Client "Erfolgs" -Fälle behandeln, die sich von "Fehler" -Fällen unterscheiden. Ich habe dort keine Wahl. Daher sollten Sie einen Fehler in Situationen zurückgeben, die der Client anders behandeln möchte , und einen Erfolg in Situationen, die der Client gleich behandeln möchte .

Wenn ich eine Abfrage durchführe, die theoretisch eine beliebige Anzahl von Ergebnissen (null, eins, zweihundert usw.) zurückgeben kann, sollten Sie "success" zurückgeben, wenn die API die vollständige Liste aller Ergebnisse liefert. Und in Fällen, in denen es viele Ergebnisse gibt, haben Sie möglicherweise eine Teilliste mit Ergebnissen zurückgegeben, um eine übermäßige Größe zu vermeiden, und es gibt einen vereinbarten Weg, wie ich die anderen Ergebnisse erhalten würde. Das liegt daran, dass ich als Kunde häufig den Fall von Null-Ergebnissen wie den Fall von mehr Ergebnissen behandeln möchte. Ich würde es vielleicht anders behandeln, aber ich möchte nicht dazu gezwungen werden.

Anders ist es in dem Fall, dass ich einen Wert nachschlage. Ich erwarte genau ein Ergebnis, den Wert, den ich suche. Und ich brauche dieses eine Ergebnis, um das, was ich tun möchte, sinnvoll fortzusetzen. Hier ist es viel akzeptabler, einen Status 404 für den Fall zurückzugeben, dass kein Wert vorhanden ist, da ich diesen Fall ohnehin anders behandeln muss.

Zusammenfassung: Wenn der Client eine beliebige Anzahl von Ergebnissen erwartet, von Null bis zu großen Zahlen, wird "Erfolg" zurückgegeben, wenn alle Ergebnisse geliefert werden, auch wenn die Zahl Null ist. Wenn der Client genau ein Ergebnis erwartet, geben Sie Erfolg zurück, wenn das Ergebnis gefunden wird, und einen Fehler, wenn das Ergebnis nicht gefunden wird.

gnasher729
quelle