"Nessun risultato" dovrebbe essere un errore in una risposta RESTful?

45

Descriverò un esempio:
Inizio a creare un'API per una pasticceria. L'API consentirà alle persone di cercare i loro cataloghi per prodotti da forno, ad esempio biscotti fatti in casa con cioccolato e menta tritati usando api.examplebakery.com/search?q=..... .

Qualcuno lo usa per cercare un prodotto chiamato pineapple-banana flavoured cookies e ovviamente non troverà alcun risultato.

Questo dovrebbe essere restituito come un errore? La ricerca non ha fallito, l'API ha cercato e concluso con successo non è stato possibile trovare alcun cookie. L'API non dovrebbe restituire 404 , perché l'API è stata effettivamente trovata.

    
posta Berry M. 28.09.2017 - 12:47
fonte

6 risposte

116

Quando ci sono risultati, l'output è un elenco (JSON, basato sul tuo commento). Per le query senza risultati, l'output dovrebbe essere esattamente lo stesso. L'elenco semplice contiene 0 elementi.

Quindi se la tua risposta è normalmente questa:

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

Quindi per una query con 0 risultati, dovrebbe essere questo:

{
    "results": []
}

Se includi anche metadati su quante "pagine" di risultati ci sono, link a quelle "pagine", ecc. allora ti suggerirei di dire che c'è 1 "pagina".

Lo stato HTTP dovrebbe essere lo stesso di quando ci sono risultati - 200 OK .

204 No Content potrebbe anche sembrare un'opzione, ma non è perché in effetti stai restituendo "contenuto" - la lista vuota. Se ritieni che una lista vuota non contenga il "contenuto", cosa succede se modifichi la risposta per offrire suggerimenti di ortografia? Il nucleo della risposta sarà comunque una lista vuota, ma ora c'è ancora più "contenuto".

Per ulteriori informazioni utili sui codici di stato HTTP, jpmc26 la loro risposta è da leggere.

    
risposta data 28.09.2017 - 13:07
fonte
36

Ogni volta che decidi un codice HTTP, devi sempre fare questa domanda:

What can/will/should any arbitrary client do with the response?

  1. Il client sempre deve considerare la risposta come un errore? Quindi vuoi 4xx o 5xx, a seconda che il problema sia l'input del client o i processi del server.
  2. Dovrebbe invece il client effettuare una richiesta da qualche altra parte? Quindi 3xx è per te.
  3. Il server ha fatto ciò che il cliente ha chiesto (riuscito)? Questo è 2xx.

Decidi sempre su quale intervallo inserire il tuo codice di risposta. Facendo così rapidamente si eliminano molti codici di risposta come opzioni, e (forse ancora più importante) rende molto più semplice seguire la semantica dei codici. Consulta le sezioni iniziali della documentazione del codice HTTP per le spiegazioni di ciò che ciascuna categoria di codici rappresenta.

In questo caso, il client ha richiesto un elenco di risultati a cui è stato assegnato un filtro da un endpoint valido e esistente e dispone dell'autorizzazione per accedervi. Il server è stato in grado di elaborare la richiesta e determinare i dati appropriati da restituire (senza elementi), pertanto la richiesta è stata eseguita correttamente. Succede solo che il filtro che hanno dato ha filtrato tutti i risultati. Non è compito del server determinare se questo è ciò che il cliente desidera o no, poiché questo potrebbe essere un risultato previsto per alcuni client. Se è in qualche modo un problema per il codice client, è responsabilità del cliente determinare, controllare e gestire in modo appropriato. Quindi questo è chiaramente 2xx.

Ora la domanda è: "Quale 2xx?" Questo dipende da come si intende che il server risponda.

  • Rispedirai una rappresentazione di una lista vuota, come alcune altre risposte descrivono? In tal caso, si desidera 200. 200 significa che il server non ha riscontrato problemi e ha una rappresentazione dei risultati per il cliente da consumare. Questo è probabilmente il modo più conveniente di rispondere per i tuoi consumatori, che possono solo analizzare la risposta se ci sono risultati o meno e quindi capire come gestire da soli una lista vuota.
  • 204 non è semanticamente sbagliato qui, ma dovresti rispondere con nessun corpo del messaggio qualunque . Ciò significa che tutto il codice cliente dovrebbe verificare esplicitamente i diversi codici HTTP (o almeno per la mancanza di un corpo del messaggio) e gestirli separatamente. È scomodo e più probabile che porti a clienti con un comportamento scarso.

Gli altri non sono affatto applicabili:

  • 201 è fuori questione. Non hai creato risorse persistenti e non stai restituendo una posizione a una risorsa creata.
  • 202 è fuori questione. La richiesta è stata fatta; non viene elaborato in background.
  • 203 significa che la risposta è stata modificata tra il server autorevole e il client. La tua interfaccia RESTful è il server autorevole, quindi questo non si applica qui.
  • 205 non ha senso. Non hai bisogno che il cliente cancelli o aggiorni qualcosa.
  • 206 sembra essere progettato per restituire una grande risorsa su più risposte. Richiede inoltre che il client chieda per una parte del contenuto nelle intestazioni (quindi l'impaginazione tramite stringhe di query non è idonea). Non applicabile qui.

Quindi dovrebbe essere 200 o 204 e 200 è più probabile che porti a un codice client più semplice e robusto (specialmente se si utilizza una struttura di risposta consistente contenente una lista vuota).

    
risposta data 29.09.2017 - 02:46
fonte
15

No. l'uso di 404 per indicare "la tua query è stata elaborata ma non c'erano corrispondenze" è orribile perché:

  • flusso condizionale basato sulla gestione delle eccezioni (es. forzare un risultato non eccezionale per creare e gestire un'eccezione nel client che può essere non performante e scomoda)

  • ambiguità tra la pagina "reale" non trovata, hai digitato gli errori errati dell'endpoint

La cosa da ricordare è che c'è sempre un cliente per deserializzare il messaggio e ciò che questo cliente restituisce è importante; non la serializzazione.

Se il client deve restituire null, utilizzare la serializzazione di null. Se il client deve restituire un array vuoto, utilizzare [], se il client genera un errore usa 500 e passa il messaggio di errore

    
risposta data 28.09.2017 - 17:54
fonte
9

Al di là dell'eccellente risposta di Ewan:

Se la query è il tipo che restituisce un insieme di risultati, allora il set vuoto è logicamente appropriato tanto quanto un set di uno, o un insieme di più. In generale, per le ragioni che afferma @Ewan, fa più male che bene a modificare il set vuoto in un errore e, semplicemente, non è necessario.

Se la query è il tipo che cerca e restituisce un singolo singleton (che si prevede venga trovato, ad es. corrispondenza esatta per id), allora non trovato è una possibile risposta logicamente appropriata.

    
risposta data 28.09.2017 - 18:06
fonte
5

Si presume che il codice debba compiere un'azione speciale quando non ci sono dati restituiti, ma potrebbe non essere il caso. Il codice potrebbe semplicemente essere alla ricerca di un numero di prodotti o di aggiungere i risultati a un elenco oa un numero qualsiasi di cose. Dovresti dare un "errore" a un utente solo se c'è effettivamente un errore.

    
risposta data 28.09.2017 - 22:44
fonte
0

Quando utilizzo un'API, come client devo gestire casi "riusciti" diversi dai casi di "errore"; Non ho scelta lì. Pertanto, si dovrebbe restituire un errore in situazioni che il client vuole trattare in modo diverso, e il successo in situazioni che il client desidera trattare lo stesso.

Se faccio una query che in teoria potrebbe restituire un numero qualsiasi di risultati, zero, uno, duecento e così via, allora dovresti restituire "successo" ogni volta che l'API fornisce l'elenco completo di tutti i risultati. E possibilmente nei casi in cui ci sono molti risultati, hai restituito un elenco parziale di risultati per evitare una dimensione eccessiva, e c'è un modo concordato su come ottenere gli altri risultati. Questo perché, come cliente, spesso voglio gestire il caso di risultati zero come nel caso di più risultati. Potrei trattarlo in modo diverso, ma non voglio essere costretto a farlo.

È diverso nel caso in cui cerco un valore. Mi aspetto esattamente un risultato, il valore che sto cercando. E ho bisogno di quell'unico risultato per continuare quello che voglio fare in modo significativo. In questo caso è molto più accettabile restituire uno stato 404 nel caso in cui non ci sia alcun valore, perché devo comunque gestire il caso in modo diverso.

Riepilogo: se il cliente si aspetta un numero qualsiasi di risultati, da zero a numeri grandi, restituisce "successo" se tutti i risultati vengono consegnati, anche se il numero è zero. Se il cliente si aspetta esattamente un risultato, restituisce il successo se viene trovato il risultato e un errore se il risultato non viene trovato.

    
risposta data 02.10.2017 - 19:55
fonte

Leggi altre domande sui tag