Alternative RESTful per CANCELLARE il corpo della richiesta

Mentre la specifica HTTP 1.1 sembra consentire i corpi dei messaggi sulle richieste DELETE , sembra indicare che i server dovrebbero ignorarlo poiché non ci sono semantiche definite per questo.

4.3 Corpo del messaggio

Un server DOVREBBE leggere e inoltrare un messaggio-corpo su qualsiasi richiesta; se il metodo di richiesta non include la semantica definita per un corpo dell’ quadro, il corpo del messaggio DOVREBBE essere ignorato durante la gestione della richiesta.

Ho già esaminato diverse discussioni correlate su questo argomento su SO e oltre, come ad esempio:

  • Un corpo di entity framework è autorizzato per una richiesta DELETE HTTP?
  • Payloads dei metodi di richiesta HTTP
  • HTTP GET con corpo della richiesta

La maggior parte delle discussioni sembra concordare sul fatto che fornire un corpo del messaggio su DELETE possa essere consentito , ma generalmente non è raccomandato.

Inoltre, ho notato una tendenza in varie librerie client HTTP in cui sembra che vengano sempre più registrati miglioramenti per queste librerie per supportare i corpi delle richieste su DELETE. La maggior parte delle biblioteche sembra obbligare, anche se occasionalmente con un po ‘di resistenza iniziale.

Il mio caso d’uso richiede l’aggiunta di alcuni metadati richiesti su un DELETE (ad esempio il “motivo” per l’eliminazione, insieme ad altri metadati richiesti per l’eliminazione). Ho preso in considerazione le seguenti opzioni, nessuna delle quali sembra del tutto appropriata e in linea con le specifiche HTTP e / o le best practice REST:

  • Corpo del messaggio : la specifica indica che i corpi dei messaggi su DELETE non hanno valore semantico; non completamente supportato dai client HTTP; non una pratica standard
  • Intestazioni HTTP personalizzate: la richiesta di intestazioni personalizzate è generalmente in contrasto con le pratiche standard ; utilizzarli è incoerente con il resto della mia API, nessuno dei quali richiede intestazioni personalizzate; inoltre, nessuna buona risposta HTTP disponibile per indicare valori di intestazione personalizzati sbagliati (probabilmente una domanda separata del tutto)
  • Intestazioni HTTP standard : non sono appropriate intestazioni standard
  • Parametri di query – L’aggiunta di parametri di query modifica effettivamente l’URI di richiesta che viene eliminato; contro le pratiche standard
  • Metodo POST – (ad es. POST /resourceToDelete { deletemetadata } ) POST non è un’opzione semantica per l’eliminazione; POST rappresenta in realtà l’azione opposta desiderata (cioè il POST crea subordinati di risorse, ma ho bisogno di eliminare la risorsa)
  • Metodi multipli : dividere la richiesta DELETE in due operazioni (ad esempio, PUT elimina i metadati, quindi DELETE) divide in due l’operazione atomica, lasciando potenzialmente uno stato incoerente. Il motivo di eliminazione (e altri metadati correlati) non fanno parte della rappresentazione della risorsa stessa.

La mia prima preferenza sarebbe probabilmente quella di usare il corpo del messaggio, in secondo luogo alle intestazioni HTTP personalizzate; tuttavia, come indicato, ci sono alcuni aspetti negativi di questi approcci.

Esistono raccomandazioni o best practice in linea con gli standard REST / HTTP per includere tali metadati richiesti sulle richieste DELETE? Ci sono altre alternative che non ho considerato?

Nonostante alcune raccomandazioni di non utilizzare il corpo del messaggio per le richieste DELETE, questo approccio potrebbe essere appropriato in alcuni casi d’uso. Questo è l’approccio che abbiamo utilizzato dopo aver valutato le altre opzioni menzionate nella domanda / risposte e dopo aver collaborato con i consumatori del servizio.

Mentre l’uso del corpo del messaggio non è l’ideale, nessuna delle altre opzioni si adattava perfettamente. Il corpo della richiesta DELETE ci ha permesso di aggiungere facilmente e con chiarezza semantica ai dati / metadati aggiuntivi necessari per accompagnare l’operazione DELETE.

Sarei ancora aperto ad altri pensieri e discussioni, ma volevo chiudere il ciclo su questa domanda. Apprezzo i pensieri e le discussioni di tutti su questo argomento!

Quello che sembri volere è una delle due cose, nessuna delle quali è una DELETE pura:

  1. Hai due operazioni, un PUT del motivo di cancellazione seguito da un DELETE della risorsa. Una volta cancellati, i contenuti della risorsa non sono più accessibili a nessuno. La ‘ragione’ non può contenere un collegamento ipertestuale alla risorsa eliminata. O,
  2. Stai provando ad alterare una risorsa da state=active a state=deleted usando il metodo DELETE . Le risorse con stato = eliminato vengono ignorate dalla tua API principale ma potrebbero comunque essere leggibili da un amministratore o da qualcuno con accesso al database. Questo è permesso – DELETE non deve cancellare i dati di supporto per una risorsa, solo per rimuovere la risorsa esposta a quell’URI.

Qualsiasi operazione che richiede un corpo del messaggio su una richiesta DELETE può essere scomposta nel suo aspetto più generale, un POST per eseguire tutte le attività necessarie con il corpo del messaggio e un DELETE . Non vedo alcun motivo per rompere la semantica di HTTP.

Data la situazione che hai, vorrei prendere uno dei seguenti approcci:

  • Invia un PUT o PATCH : sto deducendo che l’operazione di cancellazione è virtuale, per la natura di aver bisogno di un motivo di cancellazione. Pertanto, ritengo che l’aggiornamento del record tramite un’operazione PUT / PATCH sia un approccio valido, anche se non è un’operazione DELETE di per sé.
  • Utilizzare i parametri di query : l’uri della risorsa non viene modificato. In realtà penso che questo sia anche un approccio valido. La domanda che hai collegato stava parlando di non consentire l’eliminazione se il parametro della query mancava. Nel tuo caso, avrei solo un motivo predefinito se il motivo non è specificato nella stringa di query. La risorsa sarà ancora resource/:id . Puoi renderlo rilevabile con le intestazioni di collegamento sulla risorsa per ciascun motivo (con un tag rel su ciascuna per identificare il motivo).
  • Utilizzare un endpoint separato per ragione : utilizzando una resource/:id/canceled url like resource/:id/canceled . Questo in realtà cambia l’URI della richiesta e non è sicuramente RESTful. Ancora una volta, le intestazioni dei collegamenti possono renderlo rilevabile.

Ricorda che REST non è legge o dogma. Pensalo più come guida. Quindi, quando ha senso non seguire la guida per il dominio del problema, non farlo. Assicurati solo che i tuoi utenti API siano informati della varianza.

Suggerisco di includere i metadati richiesti come parte della gerarchia URI stessa. Un esempio (Naive):

Se è necessario eliminare le voci in base a un intervallo di date, anziché passare la data di inizio e la data di fine nel corpo o come parametri di query, strutturare l’URI in modo tale da passare le informazioni richieste come parte dell’URI.

per esempio

DELETE /entries/range/01012012/31122012 – Elimina tutte le voci tra il 1 ° gennaio 2012 e il 31 dicembre 2012

Spero che questo ti aiuti.