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


52

Descriverò un esempio:
inizio a creare un'API per una pasticceria. L'API consentirà alle persone di cercare nel proprio catalogo prodotti da forno, come i biscotti fatti in casa con scaglie di cioccolato api.examplebakery.com/search?q=......

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

Questo dovrebbe essere restituito come errore? La ricerca non è fallita, l'API ha cercato e non è stato possibile trovare correttamente i cookie. L'API non dovrebbe tornare 404, perché l'API è stata effettivamente trovata.




3
@gnat: questo non è un duplicato, perché l'altra domanda riguarda una risorsa specifica, non una query su più risorse.
Greg Burghardt,

7
Analogamente, supponiamo di avere una funzione che restituisce una matrice di oggetti. Se non ci sono oggetti che corrispondono a un particolare caso d'uso, preferiresti la funzione tramite un'eccezione o restituire un array vuoto?
Kevin - Ripristina Monica il

2
@AakashM Restituire HTTP-204 a una richiesta GET è abbastanza insolito, so di non averlo visto da nessuna parte. Per quanto ne so, HTTP-204 viene solitamente utilizzato come risposta quando si modifica una risorsa sul server, ad esempio le richieste POST / PUT / DELETE.
Radu Murzea,

Risposte:


122

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 suggerirei di dire che c'è 1 "pagina".

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

204 No Contentpuò anche sembrare un'opzione, ma non è perché stai effettivamente restituendo "contenuto" - l'elenco vuoto. Se ritieni che un elenco vuoto non sia considerato "contenuto", cosa succederebbe se modificassi la risposta per offrire suggerimenti di ortografia? Il nucleo della risposta sarà ancora un elenco vuoto, ma ora c'è ancora più "contenuto".

Per informazioni più utili sui codici di stato HTTP, vale la pena leggere la loro risposta jpmc26 .


9
Questo è lo stesso tipo di pensiero del modello di oggetti null . Errori e null non sono l'unico modo per dire che qui non c'è nulla. A volte vuoi esprimere il tuo niente in silenzio. In questo modo i clienti non devono testare nulla.
candied_orange,

54
Direi che restituire un 204 è inappropriato, poiché stai restituendo contenuti. È solo che il contenuto non ha risultati, il che è distinto dal non restituire alcun contenuto.
TMN,

9
@TMN concordato - 204 non è appropriato per "nessun risultato". La tua query dovrebbe sempre restituire un array, con i risultati all'interno dell'array. Se non ci sono risultati, il client lo gestirà in modo naturale. Se il cliente desidera mostrare un testo speciale ("Nessun risultato trovato"), va bene. 204 deve essere restituito solo per un endpoint che non restituisce naturalmente un risultato.
JasonB,

1
Potresti usare 204 se stavi restituendo null serializzato come stringa vuota che ricono
Ewan,

15
Questo. La cosa importante quando si costruisce un'API RESTful è la parte API, non la tranquillità. Una buona API semplifica la vita a clienti / consumatori. Un array vuoto è più facile da gestire rispetto a valori / eccezioni / codici di stato nulli.
Guran,

37

Ogni volta che decidi un codice HTTP, dovresti sempre porre questa domanda:

Cosa può / sarà / dovrebbe fare qualsiasi cliente arbitrario con la risposta?

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

Decidi sempre in quale intervallo deve essere inserito per primo il codice di risposta. Questa operazione elimina rapidamente molti codici di risposta come opzioni e (forse ancora più importante) rende molto più semplice seguire la semantica dei codici. Vedere le sezioni iniziali della documentazione del codice HTTP per le spiegazioni di ciò che rappresenta ciascuna categoria di codici.

In questo caso, il client ha richiesto un elenco di risultati dati un filtro da un endpoint valido ed esistente e dispone dell'autorizzazione per accedervi. Il server è stato in grado di elaborare la richiesta e determinare i dati appropriati da restituire (nessun articolo), quindi la richiesta ha avuto esito positivo. Succede semplicemente che il filtro che hanno fornito ha filtrato tutti i risultati. Non spetta al server determinare se questo è ciò che il client voleva o meno, poiché potrebbe essere un risultato previsto per alcuni client. Se è in qualche modo un problema per il codice client, è responsabilità del client determinare, verificare e gestire in modo appropriato. Quindi questo è chiaramente 2xx.

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

  • Spedirai indietro una rappresentazione di un elenco vuoto, come descrivono altre risposte ? In tal caso, si desidera 200. 200 indica che il server non ha riscontrato problemi e presenta una rappresentazione dei risultati che il client deve utilizzare. Questo è probabilmente il modo più conveniente per rispondere ai tuoi consumatori, che possono semplicemente analizzare la risposta se ci sono risultati o meno e quindi capire come gestire un elenco vuoto da soli.
  • 204 non è semanticamente sbagliato qui, ma dovresti rispondere senza nessun corpo di messaggio . Ciò significa che tutto il codice client dovrebbe verificare esplicitamente la presenza di codici HTTP diversi (o almeno l'assenza di un corpo del messaggio) e gestirli separatamente. È scomodo e più probabile che conduca a clienti mal educati.

Gli altri non sono applicabili affatto:

  • 201 è fuori discussione. Non hai creato risorse permanenti e non stai restituendo una posizione a una risorsa creata.
  • 202 è fuori discussione. 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 è necessario che il client cancelli o aggiorni qualcosa.
  • 206 sembra essere progettato per restituire una grande risorsa su più risposte. Richiede inoltre che il client richieda una parte del contenuto nelle intestazioni (pertanto la paginazione 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 coerente contenente un elenco vuoto).


5
Sarebbe interessato all'opinione del downvoter. Non credo che nulla di tutto ciò sia neppure controverso.
jpmc26,

2
Non credo che i clienti debbano controllare esplicitamente 204. Tutto ciò di cui hanno bisogno è la capacità di gestire un oggetto con risposta nulla. È compito del framework HTTP gestire 204 saltando la parte "analizza il corpo". 200 con Content-Lenght 4 e body null è lo stesso.
Agent_L

1
@Agent_L Hai ragione nel dire che se il server risponde con una struttura incompatibile con la normale risposta (come mettere nulldove c'è normalmente un elenco), non trarrai benefici dalla coerenza anche con 200. Tuttavia, ciò che descrivo sta usando un risposta coerente con la struttura normale e con un elenco vuoto in cui l'elenco di risultati dovrebbe normalmente andare. 204 coglie ogni opportunità per avere una risposta così coerente. Inoltre, anche nelle librerie client HTTP che dispongono di funzioni utili, spesso (in genere?) È necessario effettuare una chiamata esplicita per analizzare JSON.
jpmc26,

@Agent_L In particolare con gli elenchi, i chiamanti spesso possono semplicemente far scorrere il loro codice normalmente su un elenco vuoto (passando ad esempio su di esso), mentre avrebbero bisogno di un controllo esplicito di qualche tipo per gestire un altro tipo di rappresentazione.
jpmc26,

16

No. L'uso di 404 per indicare "la tua query è stata elaborata ma non ci sono state corrispondenze" è terribile perché:

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

  • l'ambiguità tra la pagina "reale" non è stata trovata, è stato digitato l'errore dell'endpoint errato

La cosa da ricordare è che c'è sempre un client che deserializza il messaggio e ciò che quel client 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 deve generare un errore, utilizzare 500 e passare il messaggio di errore


2
Perché il server dovrebbe preoccuparsi di cosa sta facendo il client con le informazioni? (PS: non sono io quello che ha votato in negativo la tua risposta).
Radu Murzea,

in questo contesto il "client" è il codice in esecuzione sul dispositivo client che espone il servizio all'applicazione client. Deve essere in grado di esporre i metodi dei servizi e restituire i risultati come previsto dal servizio. È necessaria una coppia client-server per far funzionare la comunicazione
Ewan,

3
Non usare 5xx per errori del client , ovviamente. Preferisci 4xx in quel caso.
Kevin,

1
Tuttavia, non dovrebbe essere "server", non "client" nella maggior parte di questi casi? È il server che elabora la richiesta e serve una risposta, il client elabora la risposta? In tal caso un codice 5xx sarebbe OK, dato che è un errore del server, non un errore del client?
MrWhite,

2
il problema con tutti i codici di errore è che hanno un significato all'interno di http. 500 è l'unico codice adatto per quando il tuo servizio genera un'eccezione
Ewan,

9

Oltre l'ottima risposta di Ewan:

Se la query è del tipo che restituisce un set di risultati, il set vuoto è logicamente appropriato tanto quanto un set di uno o un set di più. In generale per le ragioni che afferma @Ewan, fa più male che bene trasformare l'insieme vuoto in un errore, ed è semplicemente superfluo.

Se la query è del tipo che cerca e restituisce un singolo singleton (che dovrebbe essere trovato, ad es. Corrispondenza esatta per ID), allora la risposta non trovata è una possibile risposta logicamente appropriata.


sì, l'ho pensato esattamente sulla risposta di Ewan.
Walfrat,

5

Supponete che il codice debba eseguire un'azione speciale quando non vengono restituiti dati, ma potrebbe non essere il caso. Il codice potrebbe semplicemente cercare un conteggio dei prodotti o aggiungere i risultati a un elenco o un numero qualsiasi di cose. Dovresti dare a un utente un "errore" solo se c'è effettivamente un errore.


3
"Dovresti dare a un utente un" errore "solo se c'è effettivamente un errore." - Questo. Un set di risultati vuoto quando si esegue una "ricerca" non è normalmente un "errore". Tuttavia, se la connessione al database non riuscisse a significare che la ricerca non poteva essere effettivamente eseguita, un set di risultati vuoto (e nessun errore) sarebbe altrimenti ambiguo. Un certo tipo di stato di errore sarebbe appropriato in questo caso (forse insieme a un set di risultati vuoto - a seconda di come viene definita l'API).
MrWhite,

0

Quando utilizzo un'API, come client devo gestire casi di "successo" diversi da casi di "errore"; Non ho scelta lì. Pertanto, è necessario restituire un errore in situazioni che il client desidera trattare in modo diverso e il successo in situazioni in cui 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 dei 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 zero risultati come il 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 quel risultato per continuare quello che voglio fare in modo significativo. Qui è molto più accettabile restituire uno stato 404 nel caso in cui non ci sia alcun valore, perché devo comunque gestire quel caso in modo diverso.

Riepilogo: se il client prevede 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 client prevede esattamente un risultato, restituisce esito positivo se viene trovato il risultato e un errore se il risultato non viene trovato.

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.