Um corpo de entidade é permitido para uma solicitação HTTP DELETE?
717
Ao emitir uma solicitação HTTP DELETE, o URI da solicitação deve identificar completamente o recurso a ser excluído. No entanto, é permitido adicionar metadados extras como parte do corpo da entidade da solicitação?
No ASP.NET WebApi 2 FromBody, os parâmetros são ignorados para os pontos de extremidade HttpDelete.
Jenny O'Reilly
2
Eu tenho uma preocupação semelhante, mas meu caso é diferente. Quero emitir uma solicitação de exclusão em lote quando desejar excluir cem objetos. Certamente, é um grande aumento de desempenho para redes pré-HTTP 2.0.
Singagirl 19/09/16
1
Houve alguma alteração no HTTP / 2?
Jyotman Singh
Respostas:
570
A especificação não a proíbe ou desencoraja explicitamente, então eu diria que é permitido.
Se uma solicitação DELETE incluir um corpo da entidade, o corpo será ignorado [...]
Além disso, aqui está o que o RFC2616 (HTTP 1.1) tem a dizer em relação aos pedidos:
um corpo da entidade está presente apenas quando um corpo da mensagem está presente (seção 7.2)
a presença de um corpo da mensagem é sinalizada pela inclusão de um cabeçalho Content-Lengthou Transfer-Encoding(seção 4.3)
um corpo da mensagem não deve ser incluído quando a especificação do método de solicitação não permitir o envio de um corpo da entidade (seção 4.3)
um corpo da entidade é explicitamente proibido apenas em solicitações TRACE, todos os outros tipos de solicitação são irrestritos (seção 9 e 9.8 especificamente)
Para respostas, isso foi definido:
se um corpo da mensagem está incluído depende do método de solicitação e do status da resposta (seção 4.3)
um corpo da mensagem é explicitamente proibido nas respostas às solicitações HEAD (seção 9 e 9.4 especificamente)
um corpo da mensagem é explicitamente proibido nas respostas 1xx (informativas), 204 (sem conteúdo) e 304 (não modificadas) (seção 4.3)
todas as outras respostas incluem um corpo da mensagem, embora possa ter comprimento zero (seção 4.3)
@Jason Definitivamente. Você também pode usar cabeçalhos personalizados para passar dados adicionais, mas por que não usar o corpo da solicitação.
precisa
86
Embora a especificação não proíba pedidos DELETE de ter um corpo da mensagem, a seção 4.3 parece indicar que o corpo deve ser ignorado pelos servidores, pois não há "semântica definida" para os corpos de entidade DELETE : "Um servidor DEVE ler e encaminhar um corpo da mensagem em qualquer solicitação; se o método de solicitação não incluir semântica definida para um corpo da entidade, o corpo da mensagem DEVE ser ignorado ao manipular a solicitação . "
Shelley
72
Observe que muitos clientes também não conseguem enviar um DELETE com um corpo. Isso me queimou no Android.
Muita discussão sobre implementação combinada com especificações HTTP. Os clientes irão implementar as coisas da maneira que interpretam as especificações, não confunda isso com o significado das especificações. O fato é que as especificações deixam isso ambíguo. Discordo da interpretação de que, como não há semântica definida para o corpo da entidade, existe uma implicação de que ele deva ser ignorado. Eu acho que as pessoas estão trabalhando de trás para frente a partir de interpretações específicas de clientes existentes (Jersey, clientes de teste do Android etc.) e tentando justificar a interpretação, em vez de tentar se manter fiel às especificações. Os seres humanos são falíveis.
precisa saber é o seguinte
169
A atualização mais recente da especificação HTTP 1.1 ( RFC 7231 ) permite explicitamente um corpo de entidade em uma solicitação DELETE:
Uma carga útil em uma mensagem de solicitação DELETE não possui semântica definida; enviar um corpo de carga útil em uma solicitação DELETE pode fazer com que algumas implementações existentes rejeitem a solicitação.
a versão não aprovada mais recente da especificação remove esse requisito. A versão mais recente aprovada ainda é a RFC2616 citada acima.
BishopZ
4
Qual versão? A versão 20 ainda possui a mesma redação da versão 19 que eu vinculei acima: "Os corpos em solicitações DELETE não possuem semântica definida. Observe que o envio de um corpo em uma solicitação DELETE pode fazer com que algumas implementações existentes rejeitem a solicitação."
grzes
11
A versão 26 sugere que você pode permitir um corpo: 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.Portanto, ele vem com um aviso de compatibilidade com versões anteriores, sugerindo que o próximo padrão esteja dizendo: 'sim! DELETEpode ter um corpo.
Pure.Krome
4
A seção 4.3.5 da RFC 7231 finaliza o idioma da versão 26 com A payload within a DELETE request message has no defined semantics. Então o corpo é permitido.
mndrix
6
O corpo é permitido, mas não deve ser relevante para a solicitação. Não há absolutamente nenhum sentido em usá-lo.
Evert
55
Algumas versões do Tomcat e Jetty parecem ignorar um corpo de entidade se ele estiver presente. O que pode ser um incômodo se você pretende recebê-lo.
Você deve obter uma exceção de bloqueio otimista. Releia o registro, veja se é importante e talvez não o exclua.
Outro motivo para usá-lo é excluir vários registros por vez (por exemplo, uma grade com caixas de seleção de seleção de linha).
DELETE /messages
[{id:1, version:2},
{id:99, version:3}]
204 No Content
Observe que cada mensagem tem sua própria versão. Talvez você possa especificar várias versões usando vários cabeçalhos, mas, por George, isso é mais simples e muito mais conveniente.
Isso funciona no Tomcat (7.0.52) e no Spring MVC (4.05), possivelmente também nas versões anteriores:
@RestController
public class TestController {
@RequestMapping(value="/echo-delete", method = RequestMethod.DELETE)
SomeBean echoDelete(@RequestBody SomeBean someBean) {
return someBean;
}
}
Ter corpos em GET (e DELETE) está claramente maltratando HTTP e REST. Existem outros mecanismos para lidar com o controle de concorrência (por exemplo, If-Modified-Since e etags).
187 Bruno
19
Como é maltratá-lo claramente quando a especificação não proíbe o corpo em DELETE?
Esse é exatamente o mesmo problema: GET permite recuperar a representação do recurso identificado pelo URI e DELETE exclui o recurso identificado pelo URI. Use um URI diferente para outras versões se desejar excluir versões específicas. O URI deve ser o único identificador do recurso em HTTP / REST. Use metadados nos cabeçalhos se precisar lidar com a simultaneidade (por exemplo , If-Unmodified-Sinceou Etagé para isso que servem).
de Bruno
5
Use ETag cabeçalho em vez de um campo de versão em um corpo
A presença de um corpo da mensagem em uma solicitação é sinalizada pela inclusão de um campo de cabeçalho Content-Length ou Transfer-Encoding nos cabeçalhos da mensagem da solicitação. Um corpo da mensagem NÃO DEVE ser incluído em uma solicitação se a especificação do método da solicitação (seção 5.1.1) não permitir o envio de uma entidade na solicitação. Um servidor deve ler e encaminhar um corpo da mensagem em qualquer solicitação; se o método de solicitação não inclui semântica definida para um corpo de entidade, o corpo da mensagem DEVE ser ignorado ao manipular o pedido.
E seção 9.7:
O método DELETE solicita que o servidor de origem exclua o recurso identificado pelo Request-URI. Este método pode ser substituído por intervenção humana (ou outros meios) no servidor de origem. Não é possível garantir ao cliente que a operação foi realizada, mesmo que o código de status retornado do servidor de origem indique que a ação foi concluída com êxito. No entanto, o servidor NÃO DEVE indicar sucesso, a menos que, no momento em que a resposta seja dada, pretenda excluir o recurso ou movê-lo para um local inacessível.
Uma resposta bem-sucedida DEVE ser 200 (OK) se a resposta incluir uma entidade que descreve o status, 202 (Aceito) se a ação ainda não foi promulgada ou 204 (Sem Conteúdo) se a ação foi promulgada, mas a resposta não incluir uma entidade.
Se o pedido passa através de um cache e o Request-URI identifica uma ou mais entidades atualmente em cache, essas entradas devem ser tratadas como obsoletas. As respostas a este método não são armazenáveis em cache.c
Portanto, não é explicitamente permitido ou proibido, e há uma chance de que um proxy ao longo do caminho remova o corpo da mensagem (embora DEVE ler e encaminhar).
Se você fornecer um corpo em sua solicitação DELETE e estiver usando um balanceador de carga HTTPS do Google Cloud, ele rejeitará sua solicitação com um erro 400. Eu estava batendo minha cabeça contra uma parede e descobri que o Google, por qualquer motivo, acha que uma solicitação DELETE com um corpo é uma solicitação incorreta.
for whatever reason- porque a especificação diz o seguinte: P
Mardoxx 27/02
20
A especificação não "diz isso", apenas diz que o corpo não está definido especificamente. Se não estiver definido, e você quiser ignorá-lo, legal ... vá em frente e ignore. Mas rejeitar o pedido imediatamente parece extremo e desnecessário.
Ben Fried
1
Não confie em comportamento indefinido. É uma prática recomendada bastante comum.
Evert
@Evert existe um comportamento explicitamente indefinido (como você descreve nas especificações da linguagem C, por exemplo) e há um comportamento permitido, mas simplesmente não descrito. Usar um corpo da mensagem DELETEé o último.
Alnitak
9
Vale ressaltar que a especificação OpenAPI da versão 3.0 descartou o suporte aos métodos DELETE com um corpo:
Se você usar o cliente http apache, poderá criar facilmente suas próprias versões de GET e DELETE estendendo HttpEntityEnclosingRequestBase e fazendo com que o método getMethod () retorne GET ou DELETE. Usamos isso para conversar com elasticsearch.
Jilles van Gurp
2
link morto - ótimo. precisamos mais desses links respostas - não
cottton
3
A documentação vinculada agora contém apenas solicitações POST, sem DELETEs. Pode valer a pena adicionar uma nota a esta resposta?
dshepherd
O Elasticsearch também usa body com solicitações GET.
É absolutamente proibido ao organismo GET / DELETE ter qualquer impacto no processamento ou interpretação da solicitação
Isso significa que o corpo não deve modificar o comportamento do servidor. Então ele acrescenta:
além da necessidade de ler e descartar os bytes recebidos para manter o enquadramento da mensagem.
E, finalmente, o motivo de não proibir o corpo:
A única razão pela qual não proibimos o envio de um corpo é porque isso levaria a implementações preguiçosas, assumindo que nenhum corpo seria enviado.
Portanto, embora os clientes possam enviar o corpo da carga útil, os servidores devem descartá-lo e as APIs não devem definir uma semântica para o corpo da carga útil nessas solicitações.
Uma carga útil em uma mensagem de solicitação DELETE não possui semântica definida; enviar um corpo de carga em uma solicitação DELETE pode fazer com que algumas implementações existentes rejeitem a solicitação. https://tools.ietf.org/html/rfc7231#page-29
Usar a POSTnão é uma boa maneira RESTy de criar novos recursos, porque a semântica das respostas POST não é clara, especialmente no contexto dos cabeçalhos de Localização. Você está essencialmente deixando o HTTP para trás e empilhando o RPC no topo. A "maneira HTTP / REST" apropriada é criar recursos usando PUTo If-None-Match: *cabeçalho (ou especificando métodos HTTP apropriados, consulte MKCOLetc).
hnh 22/03/19
4
Eu não acho que uma boa resposta para isso tenha sido publicada, embora tenha havido muitos ótimos comentários sobre as respostas existentes. Vou levantar a essência desses comentários para uma nova resposta:
Uma carga útil em uma mensagem de solicitação DELETE não possui semântica definida; enviar um corpo de carga em uma solicitação DELETE pode fazer com que algumas implementações existentes rejeitem a solicitação.
O que eu perdi das outras respostas foi a implicação. Sim, é permitido incluir um corpo nos DELETEpedidos, mas é semanticamente sem sentido. O que isso realmente significa é que emitir uma DELETEsolicitação com um corpo de solicitação é semanticamente equivalente a não incluir um corpo de solicitação.
A inclusão de um corpo da solicitação não deve ter nenhum efeito sobre a solicitação, portanto nunca há sentido em incluí-la.
tl; dr: Tecnicamente, uma DELETEsolicitação com um corpo de solicitação é permitida, mas nunca é útil fazer isso.
"semanticamente sem sentido" não significa o mesmo que "não possui semântica definida". O primeiro significa que não pode ter nenhum significado. O último significa simplesmente que o próprio RFC não especifica o que essas semânticas podem ser. (Escrevo RFCs)
Alnitak
1
Em outras palavras, se o implementador de uma API deseja definir alguma semântica para si, é perfeitamente livre para fazê-lo.
Alnitak
1
@ Alnitak, esta é definitivamente uma má interpretação. Por essa definição, qualquer corpo de solicitação HTTP não possui semântica definida, mas DELETE e GET são especificamente chamados na especificação. Aqui está um trecho de um rascunho ainda a ser publicado, falando sobre isso especificamente sobre a solicitação GET: #:
Evert
1
Não discordo de você que isso não esteja claro nas RFCs atualmente lançadas, mas se você não acredita em mim, convidaria você a perguntar aos autores sobre a intenção deles de DELETE e GET. Você verá que está alinhado com a minha resposta. Como você, eu também estou envolvido em órgãos de normas e não sou apenas uma pessoa solitária com uma opinião sobre como a RFC deve ser interpretada.
Evert
2
Se for esse o caso, o 7231 é mal formulado e deveria ter dito "o corpo da carga DEVE ser ignorado". A que rascunho você está se referindo acima?
Alnitak
3
Caso alguém esteja executando esse teste de problema, não, isso não é universalmente suportado.
Atualmente, estou testando com o Sahi Pro e é muito evidente que uma chamada http DELETE retira todos os dados do corpo fornecidos (uma grande lista de IDs a serem excluídos em massa conforme o design do terminal).
Estive em contato com eles várias vezes, bem como enviei três pacotes separados de scripts, imagens e logs para revisão e eles ainda não confirmaram isso. Um patch com falha e uma conferência perdida pelo suporte deles mais tarde e ainda não recebi uma resposta sólida.
Estou certo de que Sahi não suporta isso e imagino que muitas outras ferramentas sigam o conjunto.
É implementado na versão mais recente do Sahi Pro. Como o Sahi usa o java para fazer chamadas HTTP, o Java teve um bug anterior à versão 1.8, que não permitirá que o usuário faça uma solicitação DELETE. Portanto, com o Java 1.8 em diante e o Sahi Pro 6.1.1 (que serão publicados em breve), as pessoas podem fazer a solicitação DELETE com body em Sahi.
Vivek V Dwivedi
-1
Pode ser que o URL abaixo do GitHUb o ajude a obter a resposta. Na verdade, o Application Server como o Tomcat, Weblogic, nega a chamada HTTP.DELETE com a carga útil da solicitação. Então, mantendo tudo isso em mente, eu adicionei um exemplo no github, por favor, dê uma olhada nisso
Respostas:
A especificação não a proíbe ou desencoraja explicitamente, então eu diria que é permitido.
A Microsoft vê da mesma maneira (posso ouvir murmúrios na platéia), afirmam no artigo do MSDN sobre o método DELETE do ADO.NET Data Services Framework :
Além disso, aqui está o que o RFC2616 (HTTP 1.1) tem a dizer em relação aos pedidos:
Content-Length
ouTransfer-Encoding
(seção 4.3)Para respostas, isso foi definido:
fonte
A atualização mais recente da especificação HTTP 1.1 ( RFC 7231 ) permite explicitamente um corpo de entidade em uma solicitação DELETE:
fonte
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.
Portanto, ele vem com um aviso de compatibilidade com versões anteriores, sugerindo que o próximo padrão esteja dizendo: 'sim!DELETE
pode ter um corpo.A payload within a DELETE request message has no defined semantics
. Então o corpo é permitido.Algumas versões do Tomcat e Jetty parecem ignorar um corpo de entidade se ele estiver presente. O que pode ser um incômodo se você pretende recebê-lo.
fonte
Um motivo para usar o corpo em uma solicitação de exclusão é o controle de concorrência otimista.
Você lê a versão 1 de um registro.
Seu colega lê a versão 1 do registro.
Seu colega altera o registro e atualiza o banco de dados, que atualiza a versão para 2:
Você tenta excluir o registro:
Você deve obter uma exceção de bloqueio otimista. Releia o registro, veja se é importante e talvez não o exclua.
Outro motivo para usá-lo é excluir vários registros por vez (por exemplo, uma grade com caixas de seleção de seleção de linha).
Observe que cada mensagem tem sua própria versão. Talvez você possa especificar várias versões usando vários cabeçalhos, mas, por George, isso é mais simples e muito mais conveniente.
Isso funciona no Tomcat (7.0.52) e no Spring MVC (4.05), possivelmente também nas versões anteriores:
fonte
If-Unmodified-Since
ouEtag
é para isso que servem).Parece-me que o RFC 2616 não especifica isso.
Na seção 4.3:
E seção 9.7:
Portanto, não é explicitamente permitido ou proibido, e há uma chance de que um proxy ao longo do caminho remova o corpo da mensagem (embora DEVE ler e encaminhar).
fonte
Se você fornecer um corpo em sua solicitação DELETE e estiver usando um balanceador de carga HTTPS do Google Cloud, ele rejeitará sua solicitação com um erro 400. Eu estava batendo minha cabeça contra uma parede e descobri que o Google, por qualquer motivo, acha que uma solicitação DELETE com um corpo é uma solicitação incorreta.
fonte
for whatever reason
- porque a especificação diz o seguinte: PDELETE
é o último.Vale ressaltar que a especificação OpenAPI da versão 3.0 descartou o suporte aos métodos DELETE com um corpo:
veja aqui e aqui para referências
Isso pode afetar sua implementação, documentação ou uso dessas APIs no futuro.
fonte
Parece que o ElasticSearch usa: https://www.elastic.co/guide/en/elasticsearch/reference/5.x/search-request-scroll.html#_clear_scroll_api
O que significa que o Netty suporta isso.
Como mencionado nos comentários, pode não ser mais o caso
fonte
Roy Fielding, na lista de correspondência HTTP, esclarece que na lista de correspondência http https://lists.w3.org/Archives/Public/ietf-http-wg/2020JanMar/0123.html e diz:
Isso significa que o corpo não deve modificar o comportamento do servidor. Então ele acrescenta:
E, finalmente, o motivo de não proibir o corpo:
Portanto, embora os clientes possam enviar o corpo da carga útil, os servidores devem descartá-lo e as APIs não devem definir uma semântica para o corpo da carga útil nessas solicitações.
fonte
Isso não está definido .
fonte
Usar DELETE com um corpo é arriscado ... Prefiro essa abordagem para operações de lista em vez de REST:
Operações regulares
GET / objects / Obtém todos os objetos
GET / object / ID Obtém um objeto com o ID especificado
POST / objetos Adiciona um novo objeto
PUT / objeto / ID Adiciona um objeto com o ID especificado, atualiza um objeto
DELETE / object / ID Exclui o objeto com o ID especificado
Todas as ações personalizadas são POST
POST / objects / addList Adiciona uma lista ou matriz de objetos incluídos no corpo
POST / objects / deleteList Exclui uma lista de objetos incluídos no corpo
POST / objects / customQuery Cria uma lista com base na consulta personalizada no corpo
Se um cliente não suportar suas operações estendidas, ele poderá trabalhar de maneira regular.
fonte
POST
não é uma boa maneira RESTy de criar novos recursos, porque a semântica das respostas POST não é clara, especialmente no contexto dos cabeçalhos de Localização. Você está essencialmente deixando o HTTP para trás e empilhando o RPC no topo. A "maneira HTTP / REST" apropriada é criar recursos usandoPUT
oIf-None-Match: *
cabeçalho (ou especificando métodos HTTP apropriados, consulteMKCOL
etc).Eu não acho que uma boa resposta para isso tenha sido publicada, embora tenha havido muitos ótimos comentários sobre as respostas existentes. Vou levantar a essência desses comentários para uma nova resposta:
Este parágrafo do RFC7231 foi citado algumas vezes, o que resume .
O que eu perdi das outras respostas foi a implicação. Sim, é permitido incluir um corpo nos
DELETE
pedidos, mas é semanticamente sem sentido. O que isso realmente significa é que emitir umaDELETE
solicitação com um corpo de solicitação é semanticamente equivalente a não incluir um corpo de solicitação.A inclusão de um corpo da solicitação não deve ter nenhum efeito sobre a solicitação, portanto nunca há sentido em incluí-la.
tl; dr: Tecnicamente, uma
DELETE
solicitação com um corpo de solicitação é permitida, mas nunca é útil fazer isso.fonte
Caso alguém esteja executando esse teste de problema, não, isso não é universalmente suportado.
Atualmente, estou testando com o Sahi Pro e é muito evidente que uma chamada http DELETE retira todos os dados do corpo fornecidos (uma grande lista de IDs a serem excluídos em massa conforme o design do terminal).
Estive em contato com eles várias vezes, bem como enviei três pacotes separados de scripts, imagens e logs para revisão e eles ainda não confirmaram isso. Um patch com falha e uma conferência perdida pelo suporte deles mais tarde e ainda não recebi uma resposta sólida.
Estou certo de que Sahi não suporta isso e imagino que muitas outras ferramentas sigam o conjunto.
fonte
Pode ser que o URL abaixo do GitHUb o ajude a obter a resposta. Na verdade, o Application Server como o Tomcat, Weblogic, nega a chamada HTTP.DELETE com a carga útil da solicitação. Então, mantendo tudo isso em mente, eu adicionei um exemplo no github, por favor, dê uma olhada nisso
https://github.com/ashish720/spring-examples
fonte
Consegui implementar a operação DELETE com um corpo de solicitação. Usei o AWS Lambda e o gateway de API da AWS e usei o idioma Go.
fonte