Quando si emette una richiesta DELETE HTTP, l'URI della richiesta deve identificare completamente la risorsa da eliminare. Tuttavia, è possibile aggiungere ulteriori metadati come parte del corpo dell'entità della richiesta?
Quando si emette una richiesta DELETE HTTP, l'URI della richiesta deve identificare completamente la risorsa da eliminare. Tuttavia, è possibile aggiungere ulteriori metadati come parte del corpo dell'entità della richiesta?
Risposte:
La specifica non la proibisce o scoraggia esplicitamente, quindi tenderei a dire che è consentita.
Microsoft lo vede allo stesso modo (posso sentire mormorii tra il pubblico), affermano nell'articolo MSDN sul metodo DELETE di ADO.NET Data Services Framework :
Se una richiesta DELETE include un corpo entità, il corpo viene ignorato [...]
Inoltre, ecco cosa ha da dire RFC2616 (HTTP 1.1) in merito alle richieste:
Content-Length
o Transfer-Encoding
header (sezione 4.3)Per le risposte, questo è stato definito:
L'ultimo aggiornamento della specifica HTTP 1.1 ( RFC 7231 ) consente esplicitamente un corpo di entità in una richiesta DELETE:
Un payload all'interno di un messaggio di richiesta DELETE non ha una semantica definita; l'invio di un corpo di payload su una richiesta DELETE potrebbe far sì che alcune implementazioni esistenti rifiutino la richiesta.
A payload within a DELETE request message has no defined semantics; sending a payload body on a DELETE request might cause some existing implementations to reject the request.
Quindi viene fornito con un avviso di compatibilità con le versioni precedenti, suggerisce che il prossimo standard dirà: 'sì! DELETE
può avere un corpo ».
A payload within a DELETE request message has no defined semantics
. Quindi il corpo è permesso.
Alcune versioni di Tomcat e Jetty sembrano ignorare un corpo di entità se è presente. Quale può essere un fastidio se intendevi riceverlo.
Un motivo per utilizzare il corpo in una richiesta di eliminazione è il controllo della concorrenza ottimistico.
Hai letto la versione 1 di un record.
GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }
Il tuo collega legge la versione 1 del record.
GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }
Il collega modifica il record e aggiorna il database, che aggiorna la versione a 2:
PUT /some-resource/1 { id:1, status:"important", version:1 }
200 OK { id:1, status:"important", version:2 }
Si tenta di eliminare il record:
DELETE /some-resource/1 { id:1, version:1 }
409 Conflict
Dovresti ottenere un'eccezione di blocco ottimista. Rileggi il record, vedi che è importante e forse non cancellalo.
Un altro motivo per usarlo è eliminare più record alla volta (ad esempio, una griglia con caselle di controllo per la selezione delle righe).
DELETE /messages
[{id:1, version:2},
{id:99, version:3}]
204 No Content
Si noti che ogni messaggio ha la sua versione. Forse puoi specificare più versioni usando più intestazioni, ma per George, questo è più semplice e molto più conveniente.
Funziona con Tomcat (7.0.52) e Spring MVC (4.05), possibilmente anche con versioni precedenti:
@RestController
public class TestController {
@RequestMapping(value="/echo-delete", method = RequestMethod.DELETE)
SomeBean echoDelete(@RequestBody SomeBean someBean) {
return someBean;
}
}
If-Unmodified-Since
O Etag
, ecco a cosa servono).
Mi sembra che RFC 2616 non lo specifichi.
Dalla sezione 4.3:
La presenza di un corpo del messaggio in una richiesta è segnalata dall'inclusione di un campo di intestazione Content-Length o Transfer-Encoding nelle intestazioni dei messaggi della richiesta. Un corpo di messaggio NON DEVE essere incluso in una richiesta se la specifica del metodo di richiesta (sezione 5.1.1) non consente l'invio di un corpo di entità nelle richieste. Un server DOVREBBE leggere e inoltrare un corpo del messaggio su qualsiasi richiesta; se il metodo di richiesta non include la semantica definita per un corpo di entità, DOVREBBE DOVREBBE essere ignorato durante la gestione della richiesta.
E sezione 9.7:
Il metodo DELETE richiede che il server di origine elimini la risorsa identificata dall'URI di richiesta. Questo metodo può essere ignorato dall'intervento umano (o altri mezzi) sul server di origine. Non è possibile garantire al client che l'operazione sia stata eseguita, anche se il codice di stato restituito dal server di origine indica che l'azione è stata completata correttamente. Tuttavia, il server NON DOVREBBE indicare successo a meno che, al momento della risposta, non intenda eliminare la risorsa o spostarla in una posizione inaccessibile.
Una risposta corretta DOVREBBE essere 200 (OK) se la risposta include un'entità che descrive lo stato, 202 (Accettato) se l'azione non è stata ancora attuata o 204 (Nessun contenuto) se l'azione è stata attuata ma la risposta non include un'entità.
Se la richiesta passa attraverso una cache e l'URI della richiesta identifica una o più entità attualmente memorizzate nella cache, tali voci DOVREBBERO essere trattate come obsolete. Le risposte a questo metodo non sono memorizzabili nella cache. C
Quindi non è esplicitamente consentito o non consentito e c'è la possibilità che un proxy lungo la strada possa rimuovere il corpo del messaggio (anche se DOVREBBE leggerlo e inoltrarlo).
Solo un avvertimento, se fornisci un corpo nella tua richiesta DELETE e stai utilizzando un bilanciamento del carico HTTPS di Google cloud, rifiuterà la tua richiesta con un errore 400. Stavo sbattendo la testa contro un muro e ho scoperto che Google, per qualsiasi motivo, pensa che una richiesta DELETE con un corpo sia una richiesta non valida.
for whatever reason
- Perché le specifiche lo dicono: P
DELETE
è il secondo.
Sembra che ElasticSearch lo usi: https://www.elastic.co/guide/en/elasticsearch/reference/5.x/search-request-scroll.html#_clear_scroll_api
Il che significa che Netty lo supporta.
Come menzionato nei commenti, potrebbe non essere più il caso
Roy Fielding sulla mailing list HTTP chiarisce che sulla mailing list http https://lists.w3.org/Archives/Public/ietf-http-wg/2020JanMar/0123.html e dice:
GET / DELETE è assolutamente vietato influire in alcun modo sull'elaborazione o l'interpretazione della richiesta
Ciò significa che il corpo non deve modificare il comportamento del server. Quindi aggiunge:
a parte la necessità di leggere e scartare i byte ricevuti al fine di mantenere l'inquadramento del messaggio.
E infine il motivo per non vietare il corpo:
L'unica ragione per cui non abbiamo vietato l'invio di un corpo è perché ciò porterebbe a implementazioni pigre supponendo che nessun corpo sarebbe stato inviato.
Pertanto, mentre i client possono inviare il corpo del payload, i server devono rilasciarlo e le API non devono definire una semantica per il corpo del payload su tali richieste.
Questo non è definito .
Un payload all'interno di un messaggio di richiesta DELETE non ha una semantica definita; l'invio di un corpo di payload su una richiesta DELETE potrebbe far sì che alcune implementazioni esistenti rifiutino la richiesta.
https://tools.ietf.org/html/rfc7231#page-29
L'uso di ELIMINA con un corpo è rischioso ... Preferisco questo approccio per le operazioni di elenco su REST:
Operazioni regolari
GET / objects / Ottiene tutti gli oggetti
GET / object / ID Ottiene un oggetto con ID specificato
POST / oggetti Aggiunge un nuovo oggetto
PUT / object / ID Aggiunge un oggetto con l'ID specificato, aggiorna un oggetto
DELETE / object / ID Elimina l'oggetto con l'ID specificato
Tutte le azioni personalizzate sono POST
POST / objects / addList Aggiunge un elenco o una matrice di oggetti inclusi nel corpo
POST / objects / deleteList Elimina un elenco di oggetti inclusi nel corpo
POST / objects / customQuery Crea un elenco basato sulla query personalizzata nel corpo
Se un client non supporta le operazioni estese, può funzionare in modo regolare.
POST
non è un buon metodo RESTy per creare nuove risorse perché la semantica delle risposte POST non è chiara, specialmente nel contesto delle intestazioni di posizione. Stai essenzialmente lasciando HTTP alle spalle e impilando RPC in cima. Il "modo HTTP / REST" corretto è quello di creare risorse usando PUT
w / If-None-Match: *
header (o specificando i metodi HTTP corretti, vedi MKCOL
ecc.).
Non credo sia stata pubblicata una buona risposta a questo, anche se ci sono stati molti grandi commenti sulle risposte esistenti. Solleverò l'essenza di quei commenti in una nuova risposta:
Questo paragrafo da RFC7231 è stato citato alcune volte, il che lo riassume.
Un payload all'interno di un messaggio di richiesta DELETE non ha una semantica definita; l'invio di un corpo di payload su una richiesta DELETE potrebbe far sì che alcune implementazioni esistenti rifiutino la richiesta.
Quello che mi mancava dalle altre risposte era l'implicazione. Sì, è consentito includere un corpo nelle DELETE
richieste, ma è semanticamente insignificante. Ciò significa veramente che l'emissione di unDELETE
richiesta con un corpo di richiesta equivale semanticamente a non includere un corpo di richiesta.
L'inclusione di un corpo della richiesta non dovrebbe avere alcun effetto sulla richiesta, quindi non ha mai senso includerla.
tl; dr: tecnicamente DELETE
è consentita una richiesta con un corpo di richiesta, ma non è mai utile farlo.
Nel caso in cui qualcuno stia eseguendo questo test di verifica, No non è universalmente supportato.
Attualmente sto testando con Sahi Pro ed è evidente che una chiamata http DELETE elimina tutti i dati del corpo forniti (un ampio elenco di ID da eliminare in blocco secondo la progettazione dell'endpoint).
Sono stato in contatto con loro diverse volte e ho inviato tre pacchetti separati di script, immagini, registri per la loro revisione e ancora non lo hanno confermato. Una patch non riuscita e una teleconferenza persa dal loro supporto in seguito e non ho ancora ottenuto una risposta solida.
Sono certo che Sahi non lo supporta e immagino che molti altri strumenti seguano la suite.
Potrebbe essere l'URL GitHUb di seguito ti aiuterà, per ottenere la risposta. In realtà, Application Server come Tomcat, Weblogic nega la chiamata HTTP.DELETE con payload di richiesta. Quindi, tenendo a mente tutte queste cose, ho aggiunto un esempio in Github, per favore date un'occhiata