REST, DELETE HTTP e parametri


135

Esiste qualcosa di non RESTful nel fornire parametri a una richiesta DELETE HTTP?


Il mio scenario è che sto modellando "Sei sicuro di volerlo eliminare?" scenario. In alcuni casi, lo stato della risorsa suggerisce che l'eliminazione richiesta potrebbe non essere valida. Probabilmente puoi immaginare alcuni scenari in cui è richiesta la conferma di un'eliminazione

La soluzione che abbiamo adottato è di passare un parametro alla richiesta di eliminazione per indicare che è possibile procedere con l'eliminazione ("? Force_delete = true")

per esempio

DELETE http://server/resource/id?force_delete=true

Credo che sia ancora riposante poiché:

(a) La semantica di DELETE non viene modificata: l'utente può comunque inviare una normale richiesta DELETE, ma ciò potrebbe non riuscire con 409 e il corpo della risposta spiegherà il perché. Dico che potrebbe non funzionare perché (per motivi che non valgono la pena spiegare) in alcune occasioni non vi è alcun motivo per sollecitare l'utente.

(b) Non c'è nulla nella tesi di Roy che suggerisca che è contro lo spirito di REST - perché dovrebbe esserci poiché HTTP è solo un'implementazione di REST, quindi perché il passaggio dei parametri HTTP è importante


Qualcuno può indicarmi un'affermazione definitiva che inchioda il motivo per cui questo non è RESTful?

Su una domanda correlata, se l'utente non specifica force_delete, allora torno 409 Conflict- è il codice di risposta più appropriato?


Azione supplementare

Dopo alcune ulteriori ricerche, penso che l'aggiunta di parametri a DELETE possa violare diversi principi.

Il primo è che l'implementazione potrebbe violare la "Uniform Interface" (vedere la sezione 5.1.5 della tesi di Roy

Aggiungendo 'force_delete' stiamo aggiungendo un ulteriore vincolo al metodo DELETE già ben definito. Questo vincolo è significativo solo per noi.

Si potrebbe anche sostenere che viola il "5.1.2 Client-Server" poiché il dialogo di conferma è in realtà un problema di interfaccia utente e, di nuovo, non tutti i client vorranno confermare l'eliminazione.

Suggerimenti qualcuno?


1
Il tuo url per la tesi di Roy contiene un ")" che causa un 404. ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm funziona.
NuclearPeon,

Risposte:


78

No, non è RESTful. L'unico motivo per cui dovresti inserire un verbo ( force_delete) nell'URI è se dovresti sovraccaricare i metodi GET / POST in un ambiente in cui i metodi PUT / DELETE non sono disponibili. A giudicare dall'uso del metodo DELETE, non è così.

409/ConflictÈ necessario utilizzare il codice di errore HTTP per le situazioni in cui esiste un conflitto che impedisce al servizio RESTful di eseguire l'operazione, ma esiste ancora la possibilità che l'utente sia in grado di risolvere il conflitto da solo. Una conferma di pre-cancellazione (dove non ci sono conflitti reali che impedirebbero la cancellazione) non è un conflitto di per sé, poiché nulla impedisce all'API di eseguire l'operazione richiesta.

Come ha detto Alex (non so chi lo abbia votato a fondo, ha ragione), questo dovrebbe essere gestito nell'interfaccia utente, perché un servizio RESTful come tale elabora solo le richieste e dovrebbe quindi essere apolide (cioè non deve fare affidamento sulle conferme tenendo premuto qualsiasi informazione sul lato server relativa a una richiesta).

Due esempi su come eseguire questa operazione nell'interfaccia utente sarebbero:

  • pre-HTML5 : * mostra una finestra di dialogo di conferma JS all'utente e invia la richiesta solo se l'utente la conferma
  • HTML5 : * utilizza un modulo con azione ELIMINA in cui il modulo conterrebbe solo i pulsanti "Conferma" e "Annulla" ("Conferma" sarebbe il pulsante di invio)

(*) Le versioni HTML precedenti alla 5 non supportano i metodi PUT e DELETE HTTP in modo nativo, tuttavia la maggior parte dei browser moderni può eseguire questi due metodi tramite chiamate AJAX. Vedi questa discussione per i dettagli sul supporto cross-browser.


Aggiornamento (basato su ulteriori indagini e discussioni):

Lo scenario in cui il servizio richiederebbe la presenza della force_delete=truebandiera viola l' interfaccia uniforme come definito nella tesi di Roy Fielding. Inoltre, come per HTTP RFC , il metodo DELETE può essere ignorato sul server di origine (client), il che implica che ciò non viene eseguito sul server di destinazione (servizio).

Pertanto, una volta che il servizio riceve una richiesta DELETE, dovrebbe elaborarla senza richiedere ulteriori conferme (indipendentemente dal fatto che il servizio esegua effettivamente l'operazione).


2
Potresti spiegare quale vincolo REST è stato violato? Considerando che gli URI dovrebbero essere opachi per il client, perché ritieni che le aspettative del client non vengano soddisfatte con l'uso di un DELETE HTTP che elimina una risorsa ma non ne elimina un'altra. Non sono sicuro che 409 sia il miglior codice di stato da restituire, ma oltre ad essere un po 'una strana implementazione, non riesco a trovare alcun vincolo REST che si sta rompendo.
Darrel Miller,

2
@Darrel: (imho) viola l'interfaccia uniforme dal metodo DELETE che non funziona secondo gli standard HTTP. Prendi in considerazione un client REST che assume un servizio REST standard: come farà il servizio a far sapere al client che deve essere aggiunto force_delete=true? Come per RFC HTTP, il metodo DELETE può essere ignorato sul server di origine (client), il che implica che ciò non viene eseguito sul server di destinazione (servizio). Quindi la mia comprensione è che una volta che il servizio riceve una richiesta DELETE, dovrebbe elaborarla senza bisogno di alcuna conferma (indipendentemente dal fatto che il servizio esegua effettivamente l'operazione).
MicE

1
@Chris, al tuo secondo punto: sì, anche questa è la mia comprensione, cioè che lo stato suggerisce un vero conflitto e non una necessità di conferma. Ho appena notato l'aggiornamento che hai fatto nella tua domanda e sono d'accordo - mentre lo stavo esaminando da solo, sono arrivato alla stessa conclusione (che questo viola l'interfaccia uniforme e che la conferma dovrebbe essere fatta sul client / UI lato). Ho anche incontrato un thread molto interessante qui, potrebbe essere d'aiuto: mail-archive.com/pylons-discuss@googlegroups.com/msg13578.html
MicE

2
@MicE Sono in larga misura d'accordo con te sul fatto che non è il modo ideale per gestire questo scenario. Sono solo un po 'esigente con l'etichetta "non è RESTful". Per un po 'qui quella frase fu lanciata contro tutto. Tuttavia, sarebbe possibile definire regole per un tipo di supporto che dicano se si tenta di ELIMINARE una risorsa e si ottiene un errore (direi 403 vietato sarebbe migliore di 409), quindi il client dovrebbe tentare ELIMINA su una risorsa correlata puntando su un "force_delete = true". In un certo senso è un po 'come l'autorizzazione. OTTIENI, ottieni 401, aggiungi di nuovo header header e OTTIENI.
Darrel Miller,

2
@Darrel: questo è un ottimo punto, grazie. E ho visto persone lanciare me stesso l'etichetta non RESTful . È possibile che al giorno d'oggi la barriera tra servizi e applicazioni Web stia diventando molto confusa, quindi un gruppo di persone può vederlo da un punto di vista di puro servizio, mentre altri lo vedono da un punto di vista misto di applicazione / servizio. Cioè credo che entri in gioco la vera domanda su come fare la conferma. @ Chris: aggiornato - grazie signore per un argomento e una discussione molto interessanti!
MicE

35

Penso che questo non sia riposante. Non credo che il servizio riposante dovrebbe gestire il requisito di forzare l'utente a confermare l'eliminazione. Lo gestirò nell'interfaccia utente.

Specificare force_delete = true ha senso se si trattasse dell'API di un programma? Se qualcuno stesse scrivendo uno script per eliminare questa risorsa, vorresti forzarlo a specificare force_delete = true per eliminare effettivamente la risorsa?


Il primo paragrafo della tua risposta è la tua opinione e lo rispetto, ma non hai indicato qualcosa in letteratura che proibisca l'uso dell'URI in questo modo: identifica ancora la risorsa e viene utilizzato il verbo HTTP più appropriato. In risposta alle tue domande; sì, avrebbe ancora senso (secondo me). Mi aspetto che uno script (forse basato su CURL) rispetti la risposta 409 e suggerisca all'utente come inviare la richiesta - tutto basato sul mio corpo di risposta
Chris McCauley

Un buon punto per confrontare l'API Web con l'API di un programma. Questo è spesso un buon modo per scoprire se un'API è RESTful o meno.
laurent,

18

È una vecchia domanda, ma ecco alcuni commenti ...

  1. In SQL, il comando DELETE accetta un parametro "CASCADE", che consente di specificare che anche gli oggetti dipendenti devono essere eliminati. Questo è un esempio di un parametro DELETE che ha senso, ma "man rm" potrebbe fornire altri. Come potrebbero essere implementati questi casi in REST / HTTP senza un parametro?
  2. @Jan, sembra essere una convenzione consolidata che la parte del percorso dell'URL identifichi una risorsa, mentre la querystring non lo fa (almeno non necessariamente). Gli esempi abbondano: ottenere la stessa risorsa ma in un formato diverso, ottenere campi specifici di una risorsa, ecc. Se consideriamo la stringa di query come parte dell'identificatore di risorsa, è impossibile avere un concetto di "viste diverse della stessa risorsa" senza ricorrere a meccanismi non RESTful come la negoziazione del contenuto HTTP (che può essere indesiderabile per molte ragioni).

Grazie per averlo aggiunto alla conversazione, anche se non è molto una conversazione poiché dura anni.
Silviot,

6

Oltre alla risposta di Alex:

Si noti che http: // server / risorsa / id? Force_delete = true identifica una risorsa diversa da http: // server / risorsa / id . Ad esempio, è una grande differenza se si cancella / customers /? Status = old o / customers /.

Jan


Non sono d'accordo, sono libero di fornire più URI per identificare la stessa risorsa.
Chris McCauley,

18
Sì, tutti sono liberi di fare un casino :-)
Jan Algermissen,

L'indicazione di URI canonici potrebbe aiutare in questo: googlewebmastercentral.blogspot.com/2009/02/…
MicE

@Chris Dovrebbe esserci un solo URI che restituisce una rappresentazione di una risorsa. Altri URI possono fare riferimento allo stesso concetto, ma fare un GET dovrebbe restituire un 303 Vedi Altro. E proprio per contrastare l'ovvia obiezione a questo, /foo.xml e /foo.json sono due risorse diverse.
Darrel Miller,

@Darrell: accetta, ma il formato non è un problema qui. Anche .format è una convenzione in Rails e in altri framework che non fanno parte di REST - dovresti usare la negoziazione del contenuto in HTTP con MIME o microformati per implementare completamente questo.
Chris McCauley,
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.