Devo restituire una risposta 204 o 404 quando non viene trovata una risorsa?


15

Sto sviluppando un semplice servizio RESTful per tornei e programmi. Quando un torneo viene creato tramite una richiesta POST contenente un corpo JSON, il torneo viene inserito in un BiMap, dichiarato come segue in un'implementazione DAO:

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

Quando viene creato un torneo, viene restituito l'ID stringa associato in modo che l' utente possa avere riferimenti futuri di quel torneo. Può ottenere informazioni dal nuovo torneo eseguendo la seguente richiesta:

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

Ma cosa succede se non viene trovato nessun torneo con tale ID? Finora, sto restituendo una risposta 204. Bene, Jersey lo sta facendo per me quando ritorna nullda uno dei suoi metodi. Questo è il metodo che corrisponde al percorso sopra:

@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;
}

La mia domanda è: è corretto restituire una 204: No Contentrisposta o dovrebbe essere 404invece una risposta, poiché la risorsa non è stata trovata?

Se dovessi cambiarlo in una 404, domanda ovvia: dovrei cambiare la firma del metodo giusto? Poiché ora un torneo (di tipo Tournament) potrebbe non essere restituito, il metodo dovrebbe apparire diverso. Dovrei usare invece il Responsetipo come tipo di ritorno?

Risposte:


32

HTTP 204significa che è stato trovato qualcosa , ma è vuoto. Ad esempio, immagina di pubblicare file di registro tramite HTTP, con richieste come http://example.com/logs/[date-goes-here] . 18 maggio 2015:

  • http://example.com/logs/2015-05-19 ritornerebbe HTTP 404, il che significa che non ci sono registri, perché, beh, è ​​difficile registrare il futuro.

  • http://example.com/logs/2015-05-18 , tuttavia, restituirebbe o HTTP 200con le voci di registro nel contenuto della risposta o HTTP 204se il file di registro è stato creato, ma non ci sono ancora registri registrati per questo Data.

Se si fornisce nullal framework come risposta a una richiesta, si presume che sia stata trovata una voce e questa voce è vuota, quindi HTTP 204. Invece, dovresti throw new NotFoundException();indicare al framework che la voce non esiste, in modo da generare un HTTP 404.

Se dovessi cambiarlo in una 404, domanda ovvia: dovrei cambiare la firma del metodo giusto?

No, non lo fai. Questa è la cosa bella throw new NotFoundException();. Funzionerà indipendentemente dal tipo di ritorno effettivo del metodo.


5
Prendere nota speciale di RFC 2616 . 204 risposte sono conformi alle specifiche solo se si omette del tutto il corpo del messaggio. In una certa misura, il punto di una risposta 204 è di dire "no, non è un caso che non abbia restituito alcun contenuto". Per espandere l'esempio di MainMa: se uno strumento di ricerca dei log sputa i file di testo (ad esempio, un wrapper sottile attorno ai file di log che sputa il file di registro così com'è), un 204 sarebbe appropriato per un file di registro vuoto. Se la risposta fosse un oggetto JSON vuoto (ad esempio, {content: ''}), una risposta 204 sarebbe inappropriata.
Brian,

" perché, beh, è ​​difficile registrare il futuro. " - Questo bit dipende da una data arbitraria; perché non renderlo qualcosa che non richiede al lettore di fingere che non sia oggi? Forse usare 2015-02-29sarebbe meglio, dato che è una data che non esiste affatto?
Finanzi la causa di Monica il


1

La tua richiesta è GET http://localhost:8080/eventscheduler/c15268ce-474a-49bd-a623-b0b865386f39.

Se http://localhost:8080/eventscheduler/non esiste come endpoint, è necessario restituire un 404. Si sta tentando di accedere a una risorsa ( /eventscheduler/) che non esiste. Ciò indicherebbe a un client su cui esiste un server localhost:8080, ma non c'è nulla eventschedulernell'endpoint.

Se http://localhost:8080/eventscheduler/esiste come endpoint ma le risorse richieste non sono disponibili, è appropriato un errore 5xx. Un buon esempio di questo potrebbe essere se un database non è in linea, dove potresti restituire un 503. Naturalmente, potresti voler restituire un errore 500 generico anziché un'istanza specifica.

Se http://localhost:8080/eventscheduler/esiste ma la cosa rappresentata da c15268ce-474a-49bd-a623-b0b865386f39non esiste, restituirei un 200 con un corpo che indica i dettagli. L'endpoint esiste, la richiesta fatta era totalmente valida e poteva essere elaborata, ma non c'era corrispondenza.

Se la richiesta del client all'endpoint non fosse valida, verranno visualizzati gli altri errori 4xx. È possibile indicare che il client non è autorizzato ad accedere all'endpoint o agli articoli richiesti con un 401 o 403 oppure è possibile utilizzare un 400 per indicare che la richiesta non è valida. Con uno di questi, ulteriori informazioni possono essere fornite nel corpo della risposta.


Non è necessario distinguere tra endpoint e risorsa. Se l'URI non corrisponde a nessuna risorsa, per qualsiasi motivo, il server dovrebbe restituire 404.
bdsl

Controlla il codice di risposta su questo sito per un esempio di un sito che fa la cosa giusta. È un sito Web, non un'API, ma si applica la stessa specifica http. softwareengineering.stackexchange.com/questions/266183385
bdsl

@bdsl Posso dirti che è assolutamente sbagliato. Ad esempio, sto interagendo con un servizio utente che può restituire un profilo utente. Diciamo che questo endpoint è /usered è usato come /user?email=test@example.com. Come consumatore API, voglio sapere se /userper qualche motivo non esiste sul server (forse è stato aggiunto nella v2 dell'API e il server è nella v1 o è stato rinominato nella v3) o se l'utente con l'e-mail test@example.comnon esiste. Il primo è un 404, il secondo è un 200 con un corpo che non indica alcun utente con quell'indirizzo e-mail.
Thomas Owens

@bdsl È carino, ma ciò non significa che sia giusto o migliore. Inoltre, non penso che sia possibile confrontare un sito Web progettato per l'interazione umana tramite un browser Web rispetto a un'API progettata per l'uso in un sistema software.
Thomas Owens

1
Questo problema è ulteriormente discusso in youtube.com/watch?v=nSKp2StlS6s
bdsl
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.