Eliminazione di una risorsa utilizzando http DELETE


124

Quindi, dato che il verbo DELETE in Http è idempotente, quando emetto la seguente richiesta, cosa dovrebbe accadere la seconda (o la terza, o la quarta, ecc ...)?

DELETE /person/123

La prima volta, la risorsa viene eliminata e restituisco un 204 (riuscito, nessun contenuto). Devo restituire un 204 alle chiamate successive o un 404 (non trovato)?

Risposte:


153

Poiché le richieste HTTP in un sistema senza stato dovrebbero essere indipendenti, i risultati di una richiesta non dovrebbero dipendere da una richiesta precedente. Considera cosa dovrebbe accadere se due utenti eseguissero un CANCELLA sulla stessa risorsa contemporaneamente. Ha senso che la seconda richiesta riceva un 404. Lo stesso dovrebbe essere vero se un utente effettua due richieste.

Immagino che avere DELETE restituisca due risposte diverse non ti sembra idempotente. Trovo utile pensare che le richieste idempotenti lascino il sistema nello stesso stato, non avendo necessariamente la stessa risposta. Quindi, indipendentemente dal fatto che si ELIMINA una risorsa esistente o si tenti di ELIMINARE una risorsa che non esiste, lo stato della risorsa server è lo stesso.


4
Grazie. Questo ha molto senso. In effetti stavo pensando che idempotente restituisse la stessa risposta.
Craig Wilson,

4
@ Craig Attento! Nel Cookbook, Subbu contraddice completamente ciò che ho appena detto. Dice che idempotenza significa che dovrebbe restituire la stessa risposta. Fortunatamente, Subbu sarà al RESTFest, quindi chiarirò con lui lì.
Darrel Miller

58
Se CANCELLATE qualcosa che non esiste, dovreste semplicemente restituire un 204 (anche se la risorsa non è mai esistita). Il cliente voleva che la risorsa sparisse e non c'è più. La restituzione di un 404 espone un'elaborazione interna non importante per il client e comporterà una condizione di errore non necessaria.
Brian

9
@DarrelMiller Immagino che il concetto chiave qui sia che non dovresti usare DELETE per verificare se esiste una risorsa, dovresti prima usare GET per quello. Quindi, se la risposta è 200, dovresti eseguire un DELETE; altrimenti non preoccuparti nemmeno di farlo. Quindi penso che abbia senso restituire sempre un 204 su DELETE.
manei_cc

10
@ Brian La RFC dice che dovrebbe comportarsi come rm. rmrestituisce un errore se non esiste. tools.ietf.org/html/rfc7231#section-4.3.5
Dax Fohl,

32

Il ricettario dei servizi web RESTful è una grande risorsa per questo. Per caso, la sua anteprima di Google mostra la pagina su CANCELLA (pagina 11):

Il metodo DELETE è idempotente. Ciò implica che il server deve restituire il codice di risposta 200 (OK) anche se il server ha eliminato la risorsa in una richiesta precedente. Ma in pratica, l'implementazione di DELETE come operazione idempotente richiede che il server tenga traccia di tutte le risorse eliminate. In caso contrario, può restituire un 404 (non trovato).


Sì, sembra una grande risorsa. Tuttavia, la sezione DELETE non viene visualizzata per me (è a pagina 23 e l'anteprima l'ha oscurata). Hai letto questo libro? Conosci la risposta alla mia domanda?
Craig Wilson,

Questo libro è un must per costruire REST (parla in particolare, non in una lingua).
yves amsellem

7
@ Craig Leggendo il ricettario, si dice che DOVRESTI restituire 200 OK anche se lo hai già cancellato. Tuttavia, in pratica ciò richiederebbe al server di tenere traccia di tutte le risorse eliminate, quindi, PUOI usare 404. Continua dicendo che i problemi di sicurezza potrebbero richiedere di restituire sempre 404. Pagina 11.
Darrel Miller

+1 secondo e consiglio vivamente il libro per la progettazione di servizi RESTful.
Paul DelRe

18
Ebbene, il libro è sbagliato. L'idempotenza non implica che il codice di stato sarà lo stesso. Ciò che è rilevante è lo stato finale del server.
Julian Reschke,

13

Sono d'accordo con ciò che ha detto la risposta scelta corrente, che il 2 ° (e 3 °, 4 °, ...) DELETE dovrebbe ottenere un 404 . E ho notato che la risposta ha 143 voti positivi ma ha anche un commento opposto che ha 54 voti positivi, quindi la comunità è divisa in 2 campi con un rapporto di circa 3: 1. Ecco ulteriori informazioni per risolvere questo lungo dibattito.

  1. Prima di tutto, NON iniziamo con cosa "io" penso, cosa "tu" pensi o cosa pensa un altro autore di libri. Cominciamo con le specifiche HTTP, cioè RFC 7231.

    • RFC 7231, sezione 4.3.5 DELETE è capitato che menzionasse solo una risposta di successo che dovrebbe essere 2xx, ma non chiamava ciò che avrebbe ottenuto una successiva DELETE. Quindi scaviamo più a fondo.
    • RFC 7231, sezione 6.5.4 404 Not Found dice che la risposta 404 è per una risorsa non esistente. Poiché nessun metodo http specifico (in particolare, non DELETE) viene chiamato per essere trattato diversamente, possiamo intuitivamente avere un'impressione (e giustamente), che la mia richiesta DELETE /some/resource/which/does/not/existdovrebbe risultare in un 404. Quindi, DELETE /some/resource/which/happened/to/be/removed/by/someone/else/five/days/agopotrebbe anche restituire un 404 Allora, perché dovrebbe DELETE /some/resource/i/deleted/five/seconds/agoessere diverso? "Ma che ne dici dell'idempotenza ?!", sento che lo stai urlando. Aspetta, stiamo per entrare in questo.
    • Storicamente, la RFC 2616, pubblicata nel 1999, era la specifica HTTP 1.1 più referenziata. Sfortunatamente la sua descrizione sull'idempotenza era vaga , il che lascia spazio a tutti questi dibattiti. Ma queste specifiche sono state sostituite da RFC 7231. Citato da RFC 7231, sezione 4.2.2 Metodi idempotenti , enfasi mia:

      Un metodo di richiesta è considerato "idempotente" se l'effetto previsto SUL SERVER di più richieste identiche con quel metodo è lo stesso dell'effetto per una singola richiesta di questo tipo. Dei metodi di richiesta definiti da questa specifica, i metodi PUT, DELETE e safe request sono idempotenti .

      Quindi, è scritto nelle specifiche, l'idempotenza è tutta una questione di effetto sul server. Il primo DELETE che restituisce un 204 e quindi il successivo DELETE che restituisce 404, tale codice di stato diverso NON rende il DELETE non idempotente. Usare questo argomento per giustificare un successivo ritorno è semplicemente irrilevante.

  2. OK, quindi non si tratta di idempotenza. Ma allora una domanda di follow-up potrebbe essere: cosa succede se scegliamo ancora di usare 204 nella successiva DELETE? Va bene?

    Buona domanda. La motivazione è comprensibile: consentire al cliente di raggiungere comunque il risultato desiderato, senza preoccuparsi della gestione degli errori. Direi che, restituire 204 nella successiva DELETE, è una "bugia bianca" lato server in gran parte innocua, che il lato client non farà immediatamente la differenza. Ecco perché ci sono circa il 25% delle persone che lo fanno in natura e apparentemente funziona ancora. Tieni presente che tale bugia può essere considerata semanticamente strana, perché GET /non-existrestituisce 404 ma DELETE /non-existdà 204, a quel punto il client capirà che il tuo servizio non è completamente conforme alla sezione 6.5.4 404 Non trovato .

    Ma voglio sottolineare che, il modo inteso suggerito dalla RFC 7231, cioè la restituzione di 404 alla successiva DELETE, non dovrebbe essere un problema in primo luogo. 3 volte più sviluppatori hanno scelto di farlo, e hai mai sentito un incidente grave o lamentato causato da un cliente che non è in grado di gestire 404? Presumibilmente, no, e questo perché, qualsiasi client decente che implementa HTTP DELETE (o qualsiasi metodo HTTP, per quella materia), non presumerebbe ciecamente che il risultato avrebbe sempre avuto successo 2xx. E poi, una volta che lo sviluppatore inizia a considerare la gestione degli errori, 404 Not Found sarebbe uno dei primi errori che vengono in mente. A quel punto, probabilmente trarrebbe una conclusione che è semanticamente sicuro che un'operazione HTTP DELETE ignori un errore 404. E lo hanno fatto.

Problema risolto.


2
+1 "L'idempotenza riguarda l'effetto sul server". Risposte meticolosamente. Molto bene! Sono un sostenitore 404 per le successive richieste DELETE.
nwayve

11

Prima CANCELLA : 200 o 204.

Eliminazioni successive : 200 o 204.

Motivazione : DELETE dovrebbe essere idempotente. Se restituisci 404 su un secondo DELETE, la tua risposta cambia da un codice di successo a un codice di errore . Il programma client potrebbe eseguire azioni errate in base al presupposto che l'eliminazione non sia riuscita.

Esempio :

  • Supponiamo che la tua operazione DELETE sia parte di un'operazione in più fasi (o una "saga") eseguita dal programma client.
  • Il programma client può essere un'app mobile che esegue una transazione bancaria, ad esempio.
  • Supponiamo che il programma client abbia un nuovo tentativo automatico per un'operazione DELETE (ha senso, perché DELETE dovrebbe essere idempotente).
  • Diciamo che il primo DELETE è stato eseguito con successo, ma la risposta 200 si è persa durante il percorso verso il programma client.
  • Il programma client riproverà l'eliminazione.
  • Se il secondo tentativo restituisce 404, il programma client potrebbe annullare l'operazione complessiva a causa di questo codice di errore.
  • Ma poiché il primo DELETE è stato eseguito correttamente sul server, il sistema potrebbe essere lasciato in uno stato incoerente .
  • Se il secondo tentativo restituisce 200 o 204, il programma client procederà come previsto.

Solo per illustrare l'uso di questo approccio, la guida allo stile dell'API HTTP per PayPal ha le seguenti linee guida:

DELETE: questo metodo DOVREBBE restituire il codice di stato 204 poiché nella maggior parte dei casi non è necessario restituire alcun contenuto poiché la richiesta è di eliminare una risorsa ed è stata eliminata con successo.

Poiché anche il metodo DELETE DEVE essere idempotente, DOVREBBE comunque restituire 204, anche se la risorsa è già stata eliminata. Di solito il consumatore dell'API non si preoccupa se la risorsa è stata eliminata come parte di questa operazione o prima. Questo è anche il motivo per cui è necessario restituire 204 anziché 404.


1
La domanda è: cosa è importante per il client, che ha cancellato la risorsa o che la risorsa è stata cancellata. E se qualche altro cliente cancellasse la risorsa durante la saga. Vuoi davvero fallire considerando che l'obiettivo del cliente è stato raggiunto?
Darrel Miller

1
@DarrelMiller Buon punto. Ciò che è più importante dipende dal contesto aziendale. Ma in generale, preferirei restituire 204 su un secondo tentativo DELETE, anche se la risorsa è stata eliminata da un altro client. Non voglio che il servizio fallisca (es. 404) dato che l'obiettivo del cliente è stato raggiunto.
Paulo Merson

2
Come altri menzionati, l'idempotenza non è ciò che è il tuo codice di risposta, è lo stato del tuo server.
Niranjan

@Niranjan Sono d'accordo che l'idempotenza riguardi lo stato del server, ma un codice di risposta diverso può indurre il client a cambiare lo stato del server inutilmente annullando una saga in corso.
Paulo Merson

@Paulo Merson quale codice restituirai se il cliente chiede la cancellazione di un oggetto che NON è MAI esistito? 204? o 404? Se restituisci sempre 204 che senso ha controllare il codice di ritorno?
frenchone
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.