Sollte ich eine 204- oder 404-Antwort zurückgeben, wenn eine Ressource nicht gefunden wird?

15

Ich entwickle einen einfachen RESTful-Service für Turniere und Zeitpläne. Wenn ein Turnier über eine POST-Anforderung erstellt wird, die einen JSON-Body enthält, wird das Turnier BiMapin eine DAO-Implementierung eingefügt , die wie folgt deklariert ist:

private BiMap<String, Tournament> tournaments = Maps.synchronizedBiMap(HashBiMap.create());

Wenn ein Turnier erstellt wird, wird die zugehörige Zeichenfolgen-ID zurückgegeben, damit der Benutzer künftig auf dieses Turnier verweisen kann. Er / sie kann Informationen vom neuen Turnier zurückerhalten, indem er / sie die folgende Anfrage ausführt:

GET http://localhost:8080/eventscheduler/c15268ce-474a-49bd-a623-b0b865386f39

Aber was ist, wenn kein Turnier mit einer solchen ID gefunden wird? Bisher gebe ich eine Antwort zurück. Nun, Jersey tut es für mich, wenn ich nullvon einer seiner Methoden zurückkehre. Dies ist die Methode, die der obigen Route entspricht:

@Path("/{id}")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Tournament getTournament(@PathParam("id") String id) {
    Optional<Tournament> optTournament = tournamentDao.getTournament(id);
    if (optTournament.isPresent())
        return optTournament.get();
    return null;
}

Meine Frage lautet: Ist es in Ordnung, eine 204: No ContentAntwort zurückzugeben, oder sollte es stattdessen eine 404Antwort sein, da die Ressource nicht gefunden wurde?

Wenn ich es in eine 404 ändern sollte, offensichtliche Frage: Ich sollte die Methodensignatur ändern, oder? Da jetzt ein Turnier (vom Typ Tournament) möglicherweise nicht zurückgegeben wird, sollte die Methode anders aussehen. Soll ich Responsestattdessen den Typ als Rückgabetyp verwenden?

Dabadaba
quelle

Antworten:

32

HTTP 204bedeutet , dass etwas wurde gefunden, aber es ist leer. Stellen Sie sich beispielsweise vor, Sie liefern Protokolldateien über HTTP mit Anforderungen wie http://example.com/logs/[date-goes-here] . Am 18. Mai 2015:

  • http://example.com/logs/2015-05-19 würde zurückkehren HTTP 404, was bedeutet, dass es keine Protokolle gibt, da es schwierig ist, die Zukunft zu protokollieren.

  • http://example.com/logs/2015-05-18 würde jedoch entweder HTTP 200mit den Protokolleinträgen im Inhalt der Antwort zurückkehren oder HTTP 204wenn die Protokolldatei erstellt wurde, aber es sind noch keine Protokolle dafür aufgezeichnet Datum.

Wenn Sie nulldas Framework als Antwort auf eine Anforderung bereitstellen , wird davon ausgegangen, dass Sie einen Eintrag gefunden haben, und dieser Eintrag ist daher leer HTTP 204. Stattdessen sollten Sie throw new NotFoundException();dem Framework mitteilen, dass der Eintrag nicht vorhanden ist, damit er einen generiert HTTP 404.

Wenn ich es in eine 404 ändern sollte, offensichtliche Frage: Ich sollte die Methodensignatur ändern, oder?

Nein, tust du nicht. Das ist das Schöne daran throw new NotFoundException();. Es funktioniert unabhängig vom tatsächlichen Rückgabetyp Ihrer Methode.

Arseni Mourzenko
quelle
5
Beachten Sie insbesondere RFC 2616 . 204 Antworten sind nur spezifikationskonform, wenn Sie den Nachrichtentext vollständig weglassen. Bis zu einem gewissen Grad lautet der Sinn einer 204-Antwort: "Nein, es ist kein Zufall, dass ich keinen Inhalt zurückgegeben habe." So erweitern Sie das Beispiel von MainMa: Wenn ein Protokollsuchwerkzeug Textdateien ausspuckt (z. B. ein dünner Wrapper um Protokolldateien, der die Protokolldatei so wie sie ist ausspuckt), ist ein 204 für eine leere Protokolldatei geeignet. Wenn die Antwort ein leeres JSON-Objekt wäre (z. B. {content: ''}), wäre eine 204-Antwort unangemessen.
Brian
" Weil es schwierig ist, die Zukunft zu protokollieren. " - Dieses Bit hängt von einem beliebigen Datum ab. Warum nicht etwas daraus machen, bei dem der Leser nicht so tun muss, als wäre es nicht heute? Vielleicht 2015-02-29wäre die Verwendung besser, da es sich um ein Datum handelt, das überhaupt nicht existiert?
Fund Monica Klage
1

Ihre Anfrage ist GET http://localhost:8080/eventscheduler/c15268ce-474a-49bd-a623-b0b865386f39.

Wenn http://localhost:8080/eventscheduler/es nicht als Endpunkt vorhanden ist, sollten Sie eine 404 zurückgeben. Sie versuchen, auf eine Ressource ( /eventscheduler/) zuzugreifen , die nicht vorhanden ist. Dies würde einem Client anzeigen, dass ein Server vorhanden ist localhost:8080, aber am eventschedulerEndpunkt befindet sich nichts .

Wenn http://localhost:8080/eventscheduler/als Endpunkt vorhanden, aber die erforderlichen Ressourcen nicht verfügbar sind, ist ein 5xx-Fehler angebracht. Ein gutes Beispiel hierfür wäre, wenn eine Datenbank offline ist und Sie einen 503 zurückgeben könnten. Natürlich möchten Sie möglicherweise nur einen generischen 500-Fehler anstelle einer bestimmten Instanz zurückgeben.

Wenn es http://localhost:8080/eventscheduler/existiert, aber das durch dargestellte Ding c15268ce-474a-49bd-a623-b0b865386f39nicht existiert, würde ich eine 200 mit einem Körper zurückgeben, der die Details angibt. Der Endpunkt ist vorhanden, die Anfrage war vollständig gültig und konnte verarbeitet werden, es gab jedoch keine Übereinstimmung.

Wenn die Anfrage Ihres Kunden an den Endpunkt nicht gültig wäre, würden Sie sich die anderen 4xx-Fehler ansehen. Sie können angeben, dass der Client nicht berechtigt ist, auf den Endpunkt oder die mit einem 401 oder 403 angeforderten Elemente zuzugreifen, oder mit einem 400 angeben, dass die Anforderung ungültig ist. Mit all diesen können zusätzliche Informationen im Antworttext bereitgestellt werden.

Thomas Owens
quelle
Es ist nicht erforderlich, zwischen dem Endpunkt und der Ressource zu unterscheiden. Wenn der URI aus irgendeinem Grund nicht mit Ressourcen übereinstimmt, sollte der Server 404 zurückgeben.
bdsl
Überprüfen Sie den Antwortcode auf dieser Site auf ein Beispiel für eine Site, die das Richtige tut. Es ist eine Website, keine API, aber es gilt dieselbe http-Spezifikation. softwareengineering.stackexchange.com/questions/266183385
bdsl
@bdsl Ich kann dir sagen, dass das absolut falsch ist. Ich interagiere beispielsweise mit einem Benutzerdienst, der ein Benutzerprofil zurückgeben kann. Angenommen, dieser Endpunkt wird /userund wird wie verwendet /[email protected]. Als API-Konsument möchte ich wissen, ob /userder Server aus irgendeinem Grund nicht vorhanden ist (möglicherweise wurde er in Version 2 der API hinzugefügt und der Server befindet sich in Version 1 oder er wurde in Version 3 umbenannt) oder ob der Benutzer die E-Mail hat [email protected]existiert nicht. Der erste ist ein 404, der zweite ist ein 200 mit einem Text, der angibt, dass kein Benutzer diese E-Mail-Adresse hat.
Thomas Owens
@bdsl Das ist schön, aber das heißt nicht, dass es richtig oder am besten ist. Ich glaube auch nicht, dass Sie eine Website, die für die menschliche Interaktion über einen Webbrowser entwickelt wurde, mit einer API vergleichen können, die für die Verwendung in einem Softwaresystem entwickelt wurde.
Thomas Owens
1
Dieses Problem wird weiter in youtube.com/watch?v=nSKp2StlS6s
bdsl