Qual è il codice di risposta REST corretto per una richiesta valida ma con dati vuoti?


332

Ad esempio, esegui una richiesta GET per users/9ma non esiste alcun utente con ID n. 9. Qual è il miglior codice di risposta?

  • 200 OK
  • 202 Accettato
  • 204 Nessun contenuto
  • 400 Richiesta non valida
  • 404 non trovato

19
Suggerimento: hai trovato l'utente 9?
Chris Pfohl,

42
Suggerimento 2: Quindi l'utente 9 non è stato trovato ?
Tomasz Nurkiewicz,

18
@IMB chi sta dicendo 204? "Nessun contenuto" indica che l'entità che stai cercando esiste, ma non ha rappresentazione. Ad esempio, se il blog con ID 15 non ha commenti e non si desidera restituire un elenco vuoto per i commenti sul numero 15 del blog: "/ blog / 15 / commenti" restituirà NoContent. D'altra parte, se esiste il blog 15, "404 Not Found" è più appropriato.
Chris Pfohl,

12
@Crisfole non intendevi ". D'altra parte se il blog 15 non esiste," 404 Not Found "è più appropriato"
gdoron supporta Monica il

15
Ho sicuramente fatto @gdoron! :) Grazie. Purtroppo sono in ritardo di circa tre anni per modificarlo e risolverlo.
Chris Pfohl,

Risposte:


249

TL; DR: utilizzare 404

Vedi questo blog . Lo spiega molto bene.

Riepilogo dei commenti del blog su 204:

  1. 204 No Content non è estremamente utile come codice di risposta per un browser (anche se secondo le specifiche HTTP i browser devono capirlo come un codice di risposta "non modificare la vista").
  2. 204 No Content è tuttavia molto utile per i servizi Web Ajax che potrebbero voler indicare il successo senza dover restituire qualcosa. (Soprattutto in casi come DELETEo POSTche non richiedono feedback).

La risposta, quindi, alla tua domanda è l'uso 404nel tuo caso. 204è un codice di risposta specializzato che non dovresti spesso tornare a un browser in risposta a GET.

Gli altri codici di risposta che sono ancora meno appropriati di 204e 404:

  1. 200dovrebbe essere restituito con il corpo di qualsiasi cosa tu abbia recuperato con successo. Non appropriato quando l'entità che stai recuperando non esiste.
  2. 202viene utilizzato quando il server ha iniziato a lavorare su un oggetto ma l'oggetto non è ancora completamente pronto. Certamente non è il caso qui. Non hai iniziato, né inizierai, la costruzione dell'utente 9 in risposta a una GETrichiesta. Questo infrange ogni sorta di regole.
  3. 400viene utilizzato in risposta a una richiesta HTTP mal formattata (ad esempio intestazioni http non corrette, segmenti ordinati in modo errato, ecc.). Questo sarà quasi certamente gestito da qualunque framework tu stia usando. Non dovresti avere a che fare con questo a meno che non stia scrivendo il tuo server da zero. Modifica : le RFC più recenti ora consentono di utilizzarne 400 per richieste semanticamente non valide.

La descrizione di Wikipedia dei codici di stato HTTP è particolarmente utile. Puoi anche vedere le definizioni nel documento HTTP / 1.1 RFC2616 su www.w3.org


8
Nota: i codici di risposta nel 200 indicano il successo. I codici di risposta nel 400 indicano un errore. Il riepilogo, punti uno e due, riguarda il 204codice di risposta (nessun contenuto).
Chris Pfohl,

227
-1 poiché mi oppongo troppo al 404 come risposta a una chiamata riuscita che non ha record da restituire. Come sviluppatore che ha a che fare con un'API per un'app non web, ho perso ore a contattare gli sviluppatori dell'API per rintracciare perché l'endpoint API che stavo chiamando non esisteva, quando in realtà sì, non aveva dati da segnalare. Per quanto riguarda un 204 non particolarmente utile per un browser, è un po 'come la coda che scuote il cane poiché la maggior parte degli usi degli endpoint API nel nostro universo di dispositivi intelligenti non sono basati su browser e quelli che probabilmente usano AJAX. Mi dispiace però togliere punti.
Matt Cashatt,

38
@MatthewPatrickCashatt sei libero di votare a piacimento. Ora finalmente capisco perché le persone mi stanno sottovalutando, ma la logica è ancora sbagliata. Quando si riceve un 404 non significa che il percorso non abbia senso, significa che non ci sono risorse in quella posizione. Punto. Questo è vero se stai richiedendo /badurlo /user/9quando un tale utente non esiste. Uno sviluppatore può aiutare aggiungendo una frase motivo migliore di "Non trovato", ma non è necessario.
Chris Pfohl,

19
@Crisfole Sono propenso a non essere d'accordo (anche se non a votare, continua a leggere), in base alla definizione W3 di 404 , in particolare The server has not found anything matching the Request-URI. Il web / application server ha infatti trovato un'AZIONE corrispondente all'URI di richiesta, sebbene il server db non l'abbia trovato. Tuttavia, dice anche This status code is commonly used when [...] no other response is applicable, quindi penso che ne convalidi un po 'l'uso (anche se non sono d'accordo / mi piace).
Daevin,

8
Non credo che tu stia affrontando il punto che sto sollevando: un 404 è pericolosamente confuso. Affidarsi a un chiamante che controlla una frase di motivazione o il corpo della risposta significa che non ti fidi del codice di stato, nel qual caso non è utile.
Adrian Baker,

364

Mi oppongo fermamente a 404 a favore di 204 o 200 con dati vuoti. O almeno uno dovrebbe usare un'entità di risposta con il 404.

La richiesta è stata ricevuta ed elaborata correttamente: ha innescato il codice dell'applicazione sul server, quindi non si può davvero dire che si trattava di un errore client e quindi l'intera classe di codici errore client (4xx) non è adatta.

Ancora più importante, 404 può accadere per una serie di motivi tecnici. Ad esempio, l'applicazione viene temporaneamente disattivata o disinstallata sul server, problemi di connessione proxy e quant'altro. Pertanto, il client non è in grado di distinguere tra un 404 che significa "set di risultati vuoto" e un 404 che significa "impossibile trovare il servizio, riprovare più tardi".

Questo può essere fatale: immagina un servizio di contabilità nella tua azienda che elenca tutti i dipendenti dovuti a un bonus annuale. Sfortunatamente, l'unica volta in cui viene chiamato restituisce un 404. Ciò significa che nessuno è dovuto per un bonus o che l'applicazione è attualmente inattiva per una nuova distribuzione?

-> Per le applicazioni che si preoccupano della qualità dei loro dati, 404 senza entità di risposta è quindi praticamente impossibile.

Inoltre, molti framework client rispondono a un 404 generando un'eccezione senza ulteriori domande. Ciò costringe lo sviluppatore del client a rilevare quell'eccezione, a valutarla e quindi a decidere in base a ciò se registrarla come errore rilevato da un componente di monitoraggio, ad esempio o ignorarlo. Neanche questo mi sembra carino.

Il vantaggio di 404 su 204 è che può restituire un'entità di risposta che può contenere alcune informazioni sul perché la risorsa richiesta non è stata trovata. Ma se ciò è veramente rilevante, allora si potrebbe anche considerare l'utilizzo di una risposta 200 OK e progettare il sistema in modo da consentire risposte di errore nei dati del payload. In alternativa, è possibile utilizzare il payload della risposta 404 per restituire al chiamante informazioni strutturate. Se riceve ad esempio una pagina HTML anziché XML o JSON che può analizzare, questo è un buon indicatore del fatto che qualcosa di tecnico è andato storto invece di una risposta "nessun risultato" che potrebbe essere valida dal punto di vista del chiamante. Oppure si potrebbe usare un'intestazione di risposta HTTP per questo.

Preferirei comunque un 204 o 200 con risposta vuota però. In questo modo lo stato dell'esecuzione tecnica della richiesta è separato dal risultato logico della richiesta. 2xx significa "esecuzione tecnica ok, questo è il risultato, affrontalo".

Penso che nella maggior parte dei casi dovrebbe essere lasciato al cliente decidere se un risultato vuoto sia accettabile o meno. Restituendo 404 senza entità di risposta nonostante una corretta esecuzione tecnica, il cliente può decidere di considerare i casi come errori che semplicemente non sono errori.

Un'altra rapida analogia: restituire 404 per "nessun risultato trovato" è come lanciare DatabaseConnectionException se una query SQL non ha restituito risultati. Può fare il lavoro, ma ci sono molte possibili cause tecniche che generano la stessa eccezione che verrebbero scambiate per un risultato valido.


30
Le ragioni tecniche per un "non trovato" sono anche note come errori del server. Quelli dovrebbero essere nel 500. In particolare: "Impossibile trovare il servizio" 503 Service Unavailable.
Chris Pfohl,

43
Il richiedente chiedeva anche una risorsa specifica: un singolo utente (non il /userspercorso, ma /users/9, cioè "L'utente noto come # 9"), quindi il confronto del 'set di risultati vuoto' non ha senso. 404 significa che l'oggetto non esiste.
Chris Pfohl,

29
404 indica semplicemente che la risorsa richiesta (in questo caso il numero utente 9) non è stata trovata. Non ha nulla a che fare con l'attivazione o meno del codice dell'applicazione, non ha nulla a che fare con la risposta di un'applicazione back-end. Un web server è la questione, non si parlava di proxy inverso nella domanda.
Chris Pfohl,

29
Il ragionamento in questa risposta è terribilmente sbagliato.
Kurt Spindler,

21
404: il client è stato in grado di comunicare con un determinato server, ma il server non è riuscito a trovare ciò che è stato richiesto. Letteralmente che: richiesta ricevuta, andava bene e correttamente formattata (cattiva richiesta 400), era autenticata o pubblica (non autorizzata 401 / vietata 403), nessun pagamento necessario (pagamento richiesto 402), il metodo di richiesta andava bene (metodo non consentito 405 ), la richiesta accetta può essere soddisfatta (406 non accettabile). 200 Ok dovrebbe essere usato quando l'utente ottiene la risorsa. Vuoto non è una risorsa. L'intervallo 400 è per gli errori del client L'intervallo 500 è per gli errori del server In breve: il ragionamento è disattivato.
Derk-Jan,

62

All'inizio, ho pensato che un 204 avrebbe avuto senso, ma dopo le discussioni, credo che il 404 sia l'unica vera risposta corretta. Considera i seguenti dati:

Utenti: John, Peter

METHOD  URL                      STATUS  RESPONSE
GET     /users                   200     [John, Peter]
GET     /users/john              200     John
GET     /users/kyle              404     Not found
GET     /users?name=kyle`        200     []
DELETE  /users/john              204     No Content

Alcuni retroscena:

  1. la ricerca restituisce un array, non ha avuto corrispondenze ma ha contenuto: un array vuoto .

  2. 404 è ovviamente meglio conosciuto per gli URL che non sono supportati dal server richiesto, ma una risorsa mancante è in realtà la stessa.
    Anche se /users/:nameabbinato users/kyle, l'utente Kyle non è una risorsa disponibile, quindi si applica ancora un 404. Non è una query di ricerca, è un riferimento diretto da un URL dinamico , quindi lo è 404.

Comunque, i miei due centesimi :)


9
Gettare il mio peso dietro questo stile per un'API REST. Nessun cliente dovrebbe chiedere / users / kyle a meno che non gli sia stato detto che la risorsa sarebbe esistita tramite una chiamata a / users o / users? Name = kyle
Gary Barker

@GaryBarker Ma poiché si tratta di "input dell'utente" in qualche modo, l'API deve ancora gestirlo correttamente. Mentre dovresti impedire il 404 nel TUO client, non puoi essere certo che sia stato effettivamente controllato in primo luogo. La progettazione dell'API deve essere eseguita senza considerare l'esatta implementazione del client, soprattutto in termini di input dell'utente verificato.
RicoBrassers,

Questa è la risposta con cui sono più d'accordo. Esempio perfetto di come voglio che le API funzionino. Anche il commento di GaryBarker è perfetto. È un errore quando cerchi qualcosa per ID e non esiste. È necessario sapere che l'ID esiste prima di effettuare la chiamata. Soprattutto perché ottenere una risposta vuota "riuscita" dà un calcio all'errore più avanti, probabilmente per alcuni "non è possibile leggere il nome della proprietà di indefinito" quando si fa user.name o qualcosa del genere.
Jamie Twells,

Che dire di una combinazione dei due. Supponendo che gli utenti abbiano amici. / utenti / Kyle / amici? name = fred. Kyle non esiste, quindi questa risposta sarebbe 404? O sarebbe 200 perché non ci importa esattamente di Kyle, ci preoccupiamo solo di cercare i suoi amici con il nome Fred?
JSextonn il

IMO che produrrebbe un 404, in quanto è una richiesta non valida: Kyle non esiste, quindi non è nemmeno possibile cercare i suoi amici.
Justus Romijn il

23

Se ci si aspetta che la risorsa esista, ma potrebbe essere vuota, direi che potrebbe essere più semplice ottenere un 200 OK con una rappresentazione che indica che la cosa è vuota.

Quindi preferirei / le cose restituiscono un 200 OK con {"Articoli": []} rispetto a un 204 senza nulla, perché in questo modo una raccolta con 0 articoli può essere trattata come una raccolta con uno o più oggetto in esso.

Lascerei semplicemente il 204 No Content for PUTs e DELETE, dove potrebbe non essere davvero una rappresentazione utile.

Nel caso in cui / cosa / 9 non esista davvero, un 404 è appropriato.


1
Sembra che tu preferisca programmare contro un'API usando una forma più astratta chiamata RPC. Piuttosto che accedere alle risorse seguendo da vicino i verbi e un url basato su risorse come customers/1/addressbook, il modo RPC è chiamare un endpoint simile GetCustomerAddressBooke ricevere i dati o essenzialmente null e non doversi preoccupare così tanto della complessità dell'HTTP. Ci sono pro e contro per entrambi.
The Muffin Man,

2
@ The Muffin Man, non sono sicuro di come si possa pretendere di sapere se preferisco REST o RPC, né perché sia ​​rilevante per una discussione su quale codice di stato tornare a una richiesta HTTP GET.
j0057,

Ho avuto alcuni orribili problemi di memorizzazione nella cache durante l'utilizzo di 204. Chrome avrebbe trattato la richiesta in modo strano e non avrebbe mostrato nulla nella rete e memorizzato nella cache il risultato precedente. Anche con tutte le intestazioni senza cache del mondo. Concordo con questa risposta, 200 sembra essere il migliore con un array / oggetto vuoto passato all'utente.
Jack

22

Nei progetti precedenti, ho usato 404. Se non c'è nessun utente 9, l'oggetto non è stato trovato. Pertanto 404 non trovato è appropriato.

Per l'oggetto esiste, ma non ci sono dati, 204 Nessun contenuto sarebbe appropriato. Penso che nel tuo caso, l'oggetto non esiste però.


14

Secondo w3 post,

200 OK

La richiesta è riuscita. Le informazioni restituite con la risposta dipendono dal metodo utilizzato nella richiesta

202 Accettato

La richiesta è stata accettata per l'elaborazione, ma l'elaborazione non è stata completata.

204 Nessun contenuto

Il server ha soddisfatto la richiesta ma non è necessario restituire un corpo-entità e potrebbe voler restituire metainformazioni aggiornate.

400 Richiesta non valida

La richiesta non è stata compresa dal server a causa di una sintassi non corretta. Il client NON DOVREBBE ripetere la richiesta senza modifiche

401 Non autorizzato

La richiesta richiede l'autenticazione dell'utente. La risposta DEVE includere un campo di intestazione WWW-Authenticate

404 non trovato

Il server non ha trovato nulla corrispondente all'URI di richiesta. Non viene fornita alcuna indicazione se la condizione è temporanea o permanente


Il post w3 riguarda i codici di stato HTTP. HTTP non è identico a REST. REST utilizza principalmente, ma non necessariamente, HTTP come protocollo di trasporto. 404 è un codice di errore di trasporto HTTP. Se REST sarebbe uguale a HTTP, non dovrebbe essere chiamato HTTP?
anneb

1
@anneb Come hai detto, REST utilizza HTTP, quindi questa risposta ha perfettamente senso. REST non è HTTP, REST non è comunque un protocollo. Non è necessario che REST sia identico (o uguale a HTTP) affinché questa risposta non abbia senso.
Koray Tugay,

@Koray Tugay: la ricerca di Google utilizza anche http, quindi in base a questa risposta la ricerca di Google dovrebbe rispondere allo stato http 404 se nulla corrisponde alla ricerca?
anneb

@anneb Ricerca Google menzioni un'applicazione RESTful? Io non la penso così. Quindi la risposta sarà no. Tornando alla domanda originale e questa risposta invece di cadere in una tana di coniglio .. Se un giorno la Ricerca Google crea un'API RESTful (o forse già lo fa, non lo so) potrebbe tornare 204 No Contentquando non trova risultati. No 404, ha un risultato per te, ma non ha contenuto ..
Koray Tugay

13

Per riassumere o semplificare,

2xx: dati opzionali: URI ben formato: i criteri non fanno parte dell'URI: se i criteri sono facoltativi che possono essere specificati in @RequestBody e @RequestParam dovrebbe portare a 2xx. Esempio: filtro per nome / stato

4xx: dati previsti: URI non ben formato: i criteri fanno parte dell'URI: se i criteri sono obbligatori che possono essere specificati solo in @PathVariable, dovrebbe portare a 4xx. Esempio: ricerca per ID univoco.

Quindi per la situazione richiesta: "utenti / 9" sarebbe 4xx (forse 404) Ma per "utenti? Nome = superman" dovrebbe essere 2xx (forse 204)


12

Ci sono due domande. Uno nel titolo e uno nell'esempio. Penso che ciò abbia in parte portato alla quantità di controversie su quale risposta sia appropriata.

Il titolo della domanda chiede dati vuoti. I dati vuoti sono comunque dati ma non sono uguali a nessun dato. Quindi questo suggerisce di richiedere un set di risultati, cioè un elenco, forse da /users. Se un elenco è vuoto, rimane comunque un elenco, pertanto un 204 (nessun contenuto) è più appropriato. Hai appena richiesto un elenco di utenti e ne è stato fornito uno, sembra che non abbia alcun contenuto.

L'esempio fornito invece chiede un oggetto specifico, un utente, /users/9. Se l'utente n. 9 non viene trovato, non viene restituito alcun oggetto utente. Hai richiesto una risorsa specifica (un oggetto utente) e non ti è stata data perché non è stata trovata, quindi un 404 è appropriato.

Penso che il modo per risolverlo sia se puoi usare la risposta come ti aspetteresti senza aggiungere alcuna istruzione condizionale, quindi usare un 204 altrimenti usa un 404.

Nei miei esempi posso scorrere su un elenco vuoto senza verificare se ha contenuto, ma non riesco a visualizzare i dati dell'oggetto utente su un oggetto null senza interrompere qualcosa o aggiungere un segno di spunta per vedere se è null.

Ovviamente potresti restituire un oggetto usando il modello di oggetti null se soddisfa le tue esigenze ma è una discussione per un altro thread.


9

Dopo aver esaminato la domanda, non dovresti usare il 404perché?

Basato su RFC 7231, il codice di stato corretto è204

Nelle risposte sopra ho notato 1 piccolo malinteso:

1.- la risorsa è: /users

2.- /users/8non è la risorsa, questa è: la risorsa /userscon il parametro route 8, il consumatore forse non può accorgersene e non conosce la differenza, ma l'editore lo sa e deve saperlo! ... quindi deve restituire una risposta accurata per i consumatori. periodo.

così:

Basato su RFC: 404 non è corretto perché /userssono state trovate le risorse , ma la logica eseguita utilizzando il parametro 8non ha trovato nessuno contentda restituire come risposta, quindi la risposta corretta è:204

Il punto principale qui è: 404nemmeno la risorsa è stata trovata per elaborare la logica interna

204è un: ho trovato la risorsa, la logica è stata eseguita ma non ho trovato alcun dato usando i tuoi criteri indicati nel parametro route quindi non posso restituirti nulla. Mi dispiace, verifica i tuoi criteri e chiamami di nuovo.

200: ok ho trovato la risorsa, la logica è stata eseguita (anche quando non sono costretta a restituire nulla) prendila e usala a tuo piacimento.

205: (l'opzione migliore di una risposta GET) Ho trovato la risorsa, la logica è stata eseguita, ho del contenuto per te, usalo bene, oh comunque se vuoi condividere questo in una vista, aggiorna la vista a visualizzalo.

Spero che sia d'aiuto.


8

Ciò che le risposte esistenti non elaborano è che fa la differenza se si utilizzano parametri di percorso o parametri di query.

  • In caso di parametri del percorso, il parametro fa parte del percorso della risorsa. In caso affermativo /users/9, la risposta dovrebbe essere 404perché quella risorsa non è stata trovata. /users/9è la risorsa e il risultato è unario o un errore non esiste. Questa non è una monade.
  • Nel caso di parametri di query, il parametro non fa parte del percorso della risorsa. In caso affermativo /users?id=9, la risposta dovrebbe essere 204perché la risorsa è /usersstata trovata ma non è stato in grado di restituire alcun dato. La risorsa /usersesiste e il risultato è n-ary, esiste anche se è vuoto. Se idè unico, questa è una monade.

L'utilizzo dei parametri del percorso o della query dipende dal caso d'uso. Preferisco i parametri di percorso per argomenti obbligatori, normativi o identificativi e parametri di query per argomenti facoltativi, non normativi o di attribuzione (come paging, impostazioni internazionali di fascicolazione e altro). In un'API REST, userei /users/9non /users?id=9soprattutto a causa della possibile nidificazione per ottenere "record figlio" come /users/9/ssh-keys/0ottenere la prima chiave ssh pubblica o /users/9/address/2ottenere il terzo indirizzo postale.

Preferisco usare 404. Ecco perché:

  • Le richieste di metodi unari (1 risultato) e n-ary (n risultati) non dovrebbero variare senza una buona ragione. Mi piace avere gli stessi codici di risposta, se possibile. Il numero di risultati attesi è ovviamente una differenza, diciamo, ti aspetti che il corpo sia un oggetto (unario) o una matrice di oggetti (n-ary).
  • Per n-ary, restituirei un array e, nel caso in cui non ci fossero risultati, non restituirei nessun set (nessun documento), restituirei un set vuoto (documento vuoto, come array vuoto in JSON o elemento vuoto in XML ). Cioè, è ancora 200 ma con zero record. Non c'è motivo di mettere queste informazioni sul filo se non nel corpo.
  • 204è come un voidmetodo. Io non lo uso per GET, solo per POST, PUTe DELETE. Faccio un'eccezione nel caso in GETcui gli identificatori siano parametri di query e non parametri di percorso.
  • Non trovando il record è simile NoSuchElementException, ArrayIndexOutOfBoundsExceptiono qualcosa di simile, causato dal cliente utilizzando un ID che non esiste, quindi, si tratta di un errore di cliente.
  • Dal punto di vista del codice, ottenere 204significa un ramo aggiuntivo nel codice che potrebbe essere evitato. Ciò complica il codice client e in alcuni casi complica anche il codice server (a seconda che si utilizzino monadi entità / modello o entità / modelli semplici; e consiglio vivamente di stare lontano dalle monadi entità / modello, può portare a cattivi bug dove perché della monade pensi che un'operazione abbia successo e restituisci 200 o 204 quando in realtà avresti dovuto restituire qualcos'altro).
  • Il codice client è più facile da scrivere e capire se 2xx significa che il server ha fatto ciò che il client ha richiesto e 4xx significa che il server non ha fatto ciò che il client ha richiesto ed è colpa del cliente. Non dare al client il record che il client richiesto dall'id è colpa del client, perché il client ha richiesto un id che non esiste.

Ultimo ma non meno importante: coerenza

  • GET /users/9
  • PUT /users/9 e DELETE /users/9

PUT /users/9e DELETE /users/9devono già tornare 204in caso di aggiornamento o eliminazione riusciti. Quindi cosa dovrebbero restituire nel caso in cui l'utente 9 non esistesse? Non ha senso presentare la stessa situazione come codici di stato diversi a seconda del metodo HTTP utilizzato.

Inoltre, non è una ragione normativa, ma culturale: se 204viene usato per la GET /users/9prossima cosa che accadrà nel progetto è che qualcuno pensa che il ritorno 204sia buono per i metodi n-ary. E questo complica il codice client, perché invece di limitarsi a cercare 2xxe quindi decodificare il corpo, il client deve ora verificare in modo specifico 204e in tal caso saltare la decodifica del corpo. Bud cosa fa invece il client? Creare un array vuoto? Perché non averlo sul filo, allora? Se il client crea l'array vuoto, 204 è una forma di compressione stupida. Se invece il client utilizza null, viene aperta una lattina completamente diversa di worm.



3

204 è più appropriato. Soprattutto quando si dispone di un sistema di allerta per garantire che il sito Web sia sicuro, 404 in questo caso causerebbe confusione perché non si conoscono alcuni 404 avvisi di errori di back-end o richieste normali ma la risposta è vuota.


Non dovresti restituire 404 se hai un errore di back-end.
spaventoso22

3

Direi che nessuno dei due è davvero appropriato. Come è stato detto, ad esempio da @anneb, anch'io penso che parte dei problemi derivi dall'uso di un codice di risposta HTTP per trasportare uno stato relativo a un servizio RESTful. Tutto ciò che il servizio REST ha da dire sulla propria elaborazione deve essere trasportato mediante codici specifici REST.

1

Direi che, se il server HTTP trova un servizio pronto a rispondere a una richiesta che è stata inviata, non dovrebbe rispondere con un HTTP 404 - alla fine, è stato trovato qualcosa dal server - a meno che non sia stato detto esplicitamente dal servizio che elabora la richiesta.

Supponiamo per un momento il seguente URL: http://example.com/service/return/test.

  • Il caso A è che il server "sta semplicemente cercando il file nel file system". Se non è presente, 404è corretto. Lo stesso vale, se chiede a un tipo di servizio di fornire esattamente questo file e quel servizio gli dice che non esiste nulla con quel nome.
  • Nel caso B, il server non funziona con file "reali" ma in realtà la richiesta viene elaborata da qualche altro servizio, ad esempio un qualche tipo di sistema di template. Qui, il server non può presentare alcuna pretesa sull'esistenza della risorsa in quanto non ne sa nulla (se non indicato dal servizio che la gestisce).

Senza alcuna risposta dal servizio che richiede esplicitamente un comportamento diverso, il server HTTP può dire solo 3 cose:

  • 503 se il servizio che dovrebbe gestire la richiesta non è in esecuzione o non risponde;
  • 200 altrimenti poiché il server HTTP può effettivamente soddisfare la richiesta, indipendentemente da ciò che il servizio dirà in seguito;
  • 400o 404per indicare che non esiste tale servizio (al contrario di "esiste ma offline") e non è stato trovato nient'altro.

2

Per tornare alla domanda a portata di mano: penso che l'approccio più pulito sarebbe quello di non utilizzare un codice HTTP di risposta a tutti tranne che in precedenza. Se il servizio è presente e risponde, il codice HTTP dovrebbe essere 200. La risposta dovrebbe contenere lo stato restituito dal servizio in un'intestazione separata: qui il servizio può dire

  • REST:EMPTYad es. se è stato chiesto di cercare sth. e quella ricerca è tornata vuota;
  • REST:NOT FOUNDse è stato chiesto specificamente per sth. "ID-like" - indica il nome di un file o una risorsa per ID o voce n. 24, ecc. - e quella specifica risorsa non è stata trovata (di solito è stata richiesta e non trovata una risorsa specifica);
  • REST:INVALID se una parte della richiesta inviata non è riconosciuta dal servizio.

(nota che li ho preceduti con "REST:" apposta per contrassegnare il fatto che mentre questi possono avere gli stessi valori o la stessa formulazione dei codici di risposta HTTP, sono completamente diversi)

3

Torniamo all'URL sopra e ispezioniamo il caso B in cui il servizio indica al server HTTP che non gestisce questa richiesta ma la trasmette SERVICE. HTTP serve solo ciò che viene restituito SERVICE, non sa nulla della return/testporzione poiché viene gestita da SERVICE. Se quel servizio è in esecuzione, HTTP dovrebbe tornare 200poiché ha effettivamente trovato qualcosa per gestire la richiesta.

Lo stato restituito da SERVICE(e che, come detto sopra, vorrebbe vedere in un'intestazione separata) dipende dall'azione effettivamente prevista:

  • se return/testrichiede una risorsa specifica: se esiste, restituirla con uno stato di REST:FOUND; se quella risorsa non esiste, restituire REST:NOT FOUND; questo potrebbe essere esteso per tornare REST:GONEse sappiamo che una volta è esistito e non tornerà, e REST:MOVEDse sappiamo che è diventato hollywoodiano
  • se return/testè considerata un'operazione di ricerca o simile a un filtro: se il set di risultati è vuoto, restituisce un set vuoto nel tipo richiesto e uno stato di REST:EMPTY; un insieme di risultati nel tipo richiesto e uno stato diREST:SUCCESS
  • if return/testnon è un'operazione riconosciuta da SERVICE: return REST:ERRORse è completamente errata (es. un errore di battitura retrun/test), o REST:NOT IMPLEMENTEDnel caso in cui sia pianificata per dopo.

4

Questa distinzione è molto più chiara rispetto al mescolare le due cose diverse. Renderà anche il debug più semplice e l'elaborazione solo leggermente più complessa, se non del tutto.

  • Se viene restituito un HTTP 404, il server mi dice "Non ho idea di cosa tu stia parlando". Mentre la parte REST della mia richiesta potrebbe essere perfettamente a posto, sto cercando par'Mach in tutti i posti sbagliati.
  • D'altra parte, HTTP 200 e REST: ERR mi dice che ho ricevuto il servizio ma ho fatto qualcosa di sbagliato nella mia richiesta al servizio.
  • Da HTTP 200 e REST: VUOTO, so che non ho fatto nulla di male - il server giusto, il server ha trovato il servizio, la richiesta giusta al servizio - ma il risultato della ricerca è vuoto.

Sommario

Il problema e la discussione derivano dal fatto che i codici di risposta HTTP vengono utilizzati per indicare lo stato di un servizio i cui risultati sono forniti da HTTP o per indicare sth. che non rientra nell'ambito del server HTTP stesso. A causa di questa discrepanza, non è possibile rispondere alla domanda e tutte le opinioni sono soggette a molte discussioni.

Lo stato di una richiesta elaborata da un servizio e non dal server HTTP NON DEVE DAVVERO (RFC 6919) essere fornito da un codice di risposta HTTP. Il codice HTTP DOVREBBE (RFC 2119) contiene solo informazioni che il server HTTP può fornire dal proprio ambito: vale a dire se il servizio è stato trovato per elaborare la richiesta o meno.

Invece, un modo diverso DOVREBBE essere utilizzato per comunicare al consumatore lo stato della richiesta al servizio che sta effettivamente elaborando la richiesta. La mia proposta è di farlo tramite un'intestazione specifica. Idealmente, sia il nome dell'intestazione che il suo contenuto seguono uno standard che consente ai consumatori di lavorare facilmente con queste risposte.


2

Secondo RFC7231 - page59 ( https://tools.ietf.org/html/rfc7231#page-59 ) la definizione di risposta del codice di stato 404 è:

6.5.4. 404 non trovato Il codice di stato 404 (non trovato) indica che il server di origine non ha trovato una rappresentazione corrente per la risorsa di destinazione o non è disposto a rivelarne l'esistenza. Un codice di stato 404 non indica se questa mancanza di rappresentanza è temporanea o permanente; il codice di stato 410 (Andato) è preferito a 404 se il server di origine sa, presumibilmente attraverso alcuni mezzi configurabili, che la condizione sarà probabilmente permanente. Una risposta 404 è memorizzabile nella cache per impostazione predefinita; cioè, se non diversamente indicato dalla definizione del metodo o dai controlli espliciti della cache (vedere la Sezione 4.2.2 di [RFC7234]).

E la cosa principale che mette in dubbio è la definizione di risorsa nel contesto sopra. Secondo lo stesso RFC (7231) la definizione di risorsa è:

Risorse: la destinazione di una richiesta HTTP è chiamata "risorsa". HTTP non limita la natura di una risorsa; definisce semplicemente un'interfaccia che potrebbe essere utilizzata per interagire con le risorse. Ogni risorsa è identificata da un Uniform Resource Identifier (URI), come descritto nella Sezione 2.7 di [RFC7230]. Quando un client costruisce un messaggio di richiesta HTTP / 1.1, invia l'URI di destinazione in una delle varie forme, come definito nella (Sezione 5.3 di [RFC7230]). Quando viene ricevuta una richiesta, il server ricostruisce un URI di richiesta efficace per la risorsa di destinazione (Sezione 5.5 di [RFC7230]). Un obiettivo di progettazione di HTTP è quello di separare l'identificazione delle risorse dalla semantica della richiesta, il che è reso possibile investendo la semantica della richiesta nel metodo di richiesta (Sezione 4) e alcuni campi di intestazione che modificano la richiesta (Sezione 5).

Quindi, a mio avviso, il codice di stato 404 non deve essere utilizzato su una richiesta GET riuscita con risultato vuoto (esempio: un elenco senza risultati per un filtro specifico)


2

Tali cose possono essere soggettive e ci sono alcuni argomenti interessanti e solidi su entrambi i lati. Tuttavia [a mio avviso] la restituzione di un 404 per i dati mancanti non è corretta . Ecco una descrizione semplificata per chiarire questo:

  • Richiesta: posso avere alcuni dati per favore?
  • Risorsa (endpoint API): riceverò quella richiesta per te, qui [invia una risposta di dati potenziali]

Non si è verificato alcun errore, l'endpoint è stato trovato e la tabella e le colonne sono state trovate, quindi il database è stato interrogato e i dati sono stati "correttamente" restituiti!

Ora, indipendentemente dal fatto che la "risposta positiva" contenga o meno dei dati, hai chiesto una risposta ai dati "potenziali" e che la risposta con i dati "potenziali" è stata soddisfatta. Null, empty etc sono dati validi.

200 significa semplicemente che qualunque richiesta abbiamo avuto successo. Sto richiedendo dati, nulla è andato storto con HTTP / REST e dato che i dati (anche se vuoti) sono stati restituiti, la mia "richiesta di dati" ha avuto successo.

Restituisci un 200 e lascia che il richiedente gestisca i dati vuoti come ogni specifico scenario lo garantisce!

Considera questo esempio:

  • Richiesta: query "infrazioni" tabella con ID utente 1234
  • Risorsa (endpoint API): restituisce una risposta ma i dati sono vuoti

Il fatto che questi dati siano vuoti è del tutto valido. Significa che l'utente non ha infrazioni. Questo è un 200 in quanto è tutto valido, come allora posso fare:

Non hai infrazioni, un muffin ai mirtilli!

Se lo ritieni un 404, cosa stai affermando? Le infrazioni dell'utente non sono state trovate? Ora, grammaticalmente è corretto, ma non è corretto nel mondo REST dove il successo o il fallimento riguarda la richiesta. I dati di "infrazione" per questo utente sono stati trovati correttamente, ci sono zero infrazioni - un numero reale che rappresenta uno stato valido.


[Nota sfacciata ..]

Nel tuo titolo, stai inconsciamente concordando sul fatto che 200 è la risposta corretta:

Qual è il codice di risposta REST corretto per una richiesta valida ma con dati vuoti?


Ecco alcuni aspetti da considerare nella scelta del codice di stato da utilizzare, indipendentemente dalla soggettività e dalle scelte difficili:

  1. Coerenza . Se si utilizza 404 per "nessun dato", utilizzarlo ogni volta che una risposta non restituisce alcun dato.
  2. Non utilizzare lo stesso stato per più di un significato . Se si restituisce 404 quando non è stata trovata una risorsa (ad esempio, non esiste un endpoint API ecc.) , Non utilizzarlo anche per i dati non restituiti. Questo rende solo doloroso gestire le risposte.
  3. Considerare attentamente il contesto . Che cos'è la "richiesta"? Cosa stai dicendo che stai cercando di ottenere?

1

Codifica il contenuto della risposta con un enum comune che consente al client di accenderlo e fork la logica di conseguenza. Non sono sicuro di come il tuo cliente distinguerebbe la differenza tra un "dato non trovato" 404 e un "risorsa web non trovata" 404? Non vuoi che qualcuno navighi all'utente Z / 9 e faccia meravigliare il client come se la richiesta fosse valida ma non ci fossero dati restituiti.


1

Perché non usare 410? Suggerisce che la risorsa richiesta non esiste più e che il client non dovrebbe mai fare una richiesta per quella risorsa, nel tuo caso users/9.

Puoi trovare maggiori dettagli su 410 qui: https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html


2
"il cliente non dovrebbe mai fare una richiesta" - e se quell'utente venisse creato in seguito, la tua risposta suggerisce che potresti garantire che questo utente non esisterà mai, è un presupposto molto audace e probabilmente sbagliato
Holly

Cosa ha detto Holly. Per aggiungere al suo punto: anche nel caso in cui l'utente esistesse e venisse eliminato, 410 è sbagliato, perché cosa succede se l'utente viene rimosso? (Quale tipo di caso speciale viene creato in seguito.)
Christian Hujer,

perché 410 dovrebbe essere una situazione permanente. restapitutorial.com/httpstatuscodes.html
Akostha

1

È triste che qualcosa di così semplice e ben definito sia diventato "basato sull'opinione" in questo thread.

Un server HTTP conosce solo "entità", che è un'astrazione per qualsiasi contenuto, che si tratti di una pagina Web statica, un elenco di risultati di ricerca, un elenco di altre entità, una descrizione json di qualcosa, un file multimediale, ecc. Ecc.

Si prevede che ciascuna di tali entità sia identificabile da un URL univoco, ad es

  • / user / 9 - una singola entità: un ID UTENTE = 9
  • / users: un'unica entità: un ELENCO di tutti gli utenti
  • /media/x.mp3 - una singola entità: un FILE multimediale chiamato x.mp3
  • / search - una singola entità: un CONTENUTO dinamico basato su parametri di query

Se un server trova una risorsa dall'URL specificato, non importa quale sia il suo contenuto - 2G di dati, null, {}, [] - finché esiste, sarà 200. Ma se tale entità è non noto al server, si prevede di restituire 404 "Non trovato".

Una confusione sembra provenire dagli sviluppatori che pensano che se l'applicazione ha un gestore per una determinata forma del percorso, non dovrebbe essere un errore. Agli occhi del protocollo HTTP non importa cosa è successo all'interno del server (cioè se il router predefinito ha risposto o un gestore per una forma di percorso specifica), purché non ci sia un'entità corrispondente sul server per il URL richiesto (che ha richiesto il file MP3, la pagina Web, l'oggetto utente ecc.), che restituirebbe contenuti validi (vuoti o di altro tipo), deve essere 404 (o 410 ecc.).

Un altro punto di confusione sembra riguardare "nessun dato" e "nessuna entità". Il primo riguarda il contenuto di un'entità e il secondo sulla sua esistenza.

Esempio 1:

  • Nessun dato: / gli utenti restituiscono 200 OK, body: [] perché nessuno ancora registrato
  • Nessuna entità: / users restituisce 404 perché non è presente alcun percorso / utenti

Esempio 2:

  • Nessun dato: / user / 9 restituisce return 200 OK, body: {}, perché l'ID utente = 9 non ha mai inserito i suoi dati personali
  • Nessuna entità: / user / 9 restituisce 404 perché non esiste un ID utente = 9

Esempio 3:

  • Nessun dato: / search? Name = Joe restituisce 200 OK [], perché non ci sono Joe nel DB
  • Nessuna entità: / search? Name = Joe restituisce 404 perché non esiste percorso / ricerca

0

404 sarebbe molto confuso per qualsiasi client se ritorni solo perché non ci sono dati in risposta.

Per me, il codice di risposta 200 con un corpo vuoto è sufficiente per capire che tutto è perfetto ma non ci sono dati corrispondenti ai requisiti.



0

Come affermato da molti, 404 è fuorviante e non consente al client di discriminare se l'uri richiesta non esiste o se l'uri richiesto non può recuperare la risorsa richiesta.

Lo stato 200 dovrebbe contenere dati sulle risorse, quindi non è la scelta giusta. Lo stato 204 indica qualcos'altro e non deve essere utilizzato come risposta per le richieste GET.

Tutti gli altri stati esistenti non sono applicabili, per un motivo o per l'altro.

Ho visto questo argomento essere discusso più volte in più punti. Per me è dolorosamente ovvio che per eliminare la confusione sull'argomento, è necessario uno status di successo dedicato. Qualcosa come " 209 - Nessuna risorsa da visualizzare".

Sarà uno stato 2xx perché non trovare un ID non dovrebbe essere considerato un errore del client (se i client sapessero tutto ciò che si trova nel DB del server, non avrebbero bisogno di chiedere nulla al server, no?). Questo stato dedicato affronterà tutti i problemi discussi con l'utilizzo di altri stati.

L'unica domanda è: come faccio ad accettare RFC come standard?

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.