Embora a especificação HTTP 1.1 pareça permitir corpos de mensagem em solicitações DELETE , parece indicar que os servidores devem ignorá-la, pois não há semântica definida para ela.
4.3 Corpo da Mensagem
Um servidor DEVE ler e encaminhar o 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, então o corpo da mensagem DEVERÁ ser ignorado ao lidar com a solicitação.
Já revisei várias discussões relacionadas a este tópico no SO e além, como:
- Um corpo de entidade é permitido para uma solicitação HTTP DELETE?
- Cargas úteis de métodos de solicitação HTTP
- HTTP GET com corpo da solicitação
A maioria das discussões parece concordar que fornecer um corpo de mensagem em um DELETE pode ser permitido , mas geralmente não é recomendado.
Além disso, notei uma tendência em várias bibliotecas de cliente HTTP, onde mais e mais melhorias parecem estar sendo registradas para essas bibliotecas para oferecer suporte a corpos de solicitação em DELETE. A maioria das bibliotecas parece obrigar, embora ocasionalmente com um pouco de resistência inicial.
Meu caso de uso exige a adição de alguns metadados necessários em um DELETE (por exemplo, o "motivo" da exclusão, junto com alguns outros metadados necessários para a exclusão). Considerei as seguintes opções, nenhuma das quais parece completamente apropriada e alinhada com as especificações HTTP e / ou práticas recomendadas REST:
- Corpo da mensagem - a especificação indica que os corpos da mensagem em DELETE não têm valor semântico; não é totalmente suportado por clientes HTTP; prática não padrão
- Cabeçalhos HTTP personalizados - exigir cabeçalhos personalizados é geralmente contra as práticas padrão ; usá-los é inconsistente com o resto da minha API, nenhum dos quais requer cabeçalhos personalizados; além disso, nenhuma boa resposta HTTP disponível para indicar valores de cabeçalho personalizados incorretos (provavelmente uma pergunta separada)
- Cabeçalhos HTTP padrão - Nenhum cabeçalho padrão é apropriado
- Parâmetros de consulta - Adicionar parâmetros de consulta realmente altera o URI de solicitação que está sendo excluído; contra as práticas padrão
- Método POST - (por exemplo
POST /resourceToDelete { deletemetadata }
) POST não é uma opção semântica para exclusão; O POST realmente representa a ação oposta desejada (ou seja, o POST cria subordinados de recursos, mas preciso excluir o recurso) - Métodos múltiplos - dividir a solicitação DELETE em duas operações (por exemplo, PUT excluir metadados e, em seguida, DELETE) divide uma operação atômica em duas, deixando potencialmente um estado inconsistente. O motivo da exclusão (e outros metadados relacionados) não fazem parte da representação do recurso em si.
Minha primeira preferência provavelmente seria usar o corpo da mensagem, em segundo lugar para cabeçalhos HTTP personalizados; no entanto, conforme indicado, existem algumas desvantagens para essas abordagens.
Existem recomendações ou melhores práticas em linha com os padrões REST / HTTP para incluir esses metadados necessários em solicitações DELETE? Existem outras alternativas que não considerei?
fonte
Jersey
não permitem corpo paradelete
solicitações.Respostas:
Apesar de algumas recomendações para não usar o corpo da mensagem para solicitações DELETE, essa abordagem pode ser apropriada em certos casos de uso. Essa é a abordagem que acabamos usando após avaliar as outras opções mencionadas nas perguntas / respostas e após colaborar com os consumidores do serviço.
Embora o uso do corpo da mensagem não seja ideal, nenhuma das outras opções também se encaixava perfeitamente. O corpo da solicitação DELETE nos permitiu adicionar de forma fácil e clara semântica em torno de dados / metadados adicionais que eram necessários para acompanhar a operação DELETE.
Eu ainda estaria aberto a outros pensamentos e discussões, mas gostaria de encerrar o ciclo dessa questão. Agradeço as opiniões e discussões de todos sobre este tópico!
fonte
O que você parece querer é uma de duas coisas, nenhuma das quais é pura
DELETE
:PUT
do motivo da exclusão seguida por umDELETE
do recurso. Depois de excluído, o conteúdo do recurso não fica mais acessível a ninguém. O 'motivo' não pode conter um hiperlink para o recurso excluído. Ou,state=active
parastate=deleted
usando oDELETE
método. Recursos com state = deleted são ignorados por sua API principal, mas ainda podem ser lidos por um administrador ou alguém com acesso ao banco de dados. Isso é permitido -DELETE
não precisa apagar os dados de apoio de um recurso, apenas para remover o recurso exposto naquele URI.Qualquer operação que requer um corpo de mensagem em uma
DELETE
solicitação pode ser dividida em sua forma mais geral, aPOST
para fazer todas as tarefas necessárias com o corpo da mensagem, e aDELETE
. Não vejo razão para quebrar a semântica do HTTP.fonte
PUT
razão for bem-sucedida e oDELETE
recurso falhar? Como pode o estado inconsistente ser evitado?Dada a situação que você tem, eu usaria uma das seguintes abordagens:
resource/:id
. Você pode torná-lo detectável com cabeçalhos de link no recurso para cada motivo (com umarel
tag em cada um para identificar o motivo).resource/:id/canceled
. Isso realmente altera o URI de solicitação e definitivamente não é RESTful. Novamente, os cabeçalhos dos links podem tornar isso detectável.Lembre-se de que REST não é lei ou dogma. Pense nisso mais como orientação. Portanto, quando fizer sentido não seguir as orientações para o domínio do seu problema, não o faça. Apenas certifique-se de que seus consumidores de API sejam informados sobre a variação.
fonte
/orders/:id
retornaria o mesmo recurso que/orders/:id?exclude=orderdetails
. A string de consulta está apenas dando dicas ao servidor - neste caso, para excluir detalhes do pedido na resposta (se houver suporte). Da mesma forma, se você estiver enviando DELETE para/orders/:id
ou/orders/:id?reason=canceled
ou/orders/:id?reason=bad_credit
, ainda estará agindo no mesmo recurso subjacente. Para manter uma 'interface uniforme', eu teria um motivo padrão para que o envio do parâmetro de consulta não fosse necessário./foo?123
significa que você está excluindo um recurso diferente do que se enviasse DELETE para/foo?456
.Eu sugiro que você inclua os metadados necessários como parte da própria hierarquia de URI. Um exemplo (ingênuo):
Se você precisar excluir entradas com base em um intervalo de datas, em vez de passar a data de início e a data de término no corpo ou como parâmetros de consulta, estruture o URI de forma que você passe as informações necessárias como parte do URI.
por exemplo
DELETE /entries/range/01012012/31122012
- Excluir todas as entradas entre 01 de janeiro de 2012 e 31 de dezembro de 2012Espero que isto ajude.
fonte
range
especificado nos parâmetros de consulta ou carga útil, que é o cerne desta questão: para entender a abordagem das melhores práticas para o problema que eu diria que não é isso.