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?
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?
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 :
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:
Content-Length
ou Transfer-Encoding
(seção 4.3)Para respostas, isso foi definido:
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 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.
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.
GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }
Seu colega lê a versão 1 do registro.
GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }
Seu colega altera o registro e atualiza o banco de dados, que atualiza a versão para 2:
PUT /some-resource/1 { id:1, status:"important", version:1 }
200 OK { id:1, status:"important", version:2 }
Você tenta excluir o registro:
DELETE /some-resource/1 { id:1, version:1 }
409 Conflict
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;
}
}
If-Unmodified-Since
ou Etag
é para isso que servem).
Parece-me que o RFC 2616 não especifica isso.
Na seção 4.3:
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
DELETE
é o último.
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
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:
É 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.
Isso não está definido .
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 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.
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 usando PUT
o If-None-Match: *
cabeçalho (ou especificando métodos HTTP apropriados, consulte MKCOL
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 .
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 DELETE
pedidos, mas é semanticamente sem sentido. O que isso realmente significa é que emitir uma DELETE
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.
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.
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