REST DELETE é realmente idempotente?

166

DELETE deve ser idempotente.

Se eu excluir http://example.com/account/123, ele excluirá a conta.

Se eu fizer novamente, esperaria um 404, já que a conta não existe mais? E se eu tentar EXCLUIR uma conta que nunca existiu?

Ben Noland
fonte
11
Além das respostas, sugiro não se concentrar muito na característica idempotente em geral: ela não diz nada sobre comutatividade e solicitações simultâneas. Por exemplo, N + 1 da mesma solicitação PUT "R1" deve ter o mesmo efeito, mas você não sabe se outro cliente fez uma solicitação PUT / DELETE "R2" diferente entre as suas, portanto, enquanto n R1 = R1 e m R2 = R2, algo em que você solicita intercaladas as solicitações "R1" e "R2" não necessariamente "parecerá" idempotente se você considerar apenas a perspectiva de um único cliente.
Bruno

Respostas:

188

Idempotência refere-se ao estado do sistema após a conclusão da solicitação


Em todos os casos (além dos problemas de erro - veja abaixo), a conta não existe mais.

A partir daqui

"Os métodos também podem ter a propriedade" idempotência ", pois ( além de problemas de erro ou expiração ), os efeitos colaterais de N> 0 solicitações idênticas são os mesmos de uma única solicitação. Os métodos GET, HEAD, PUT e DELETE compartilham Além disso, os métodos OPTIONS e TRACE NÃO DEVEM ter efeitos colaterais e, portanto, são inerentemente idempotentes ".


O bit principal dos efeitos colaterais de N> 0 pedidos idênticos é o mesmo que para um único pedido.

Você está certo ao esperar que o código de status seja diferente, mas isso não afeta o conceito principal de idempotência - você pode enviar a solicitação mais de uma vez sem alterações adicionais no estado do servidor.

Chris McCauley
fonte
3
Efeitos colaterais! == estado do servidor
wprl
2
@wprl Há um debate sobre o que esse "efeito colateral" realmente é. Pode ser "estado do servidor" ou pode ser uma resposta enviada ao cliente. leedavis81.github.io/is-a-http-delete-requests-idempotent
Alireza
Aqui está um argumento que 404 em uma segunda EXCLUIR pode realmente mudar o estado do servidor: stackoverflow.com/a/45194747/317522
Paulo Merson
1
@PauloMerson Obrigado, pessoalmente, acho que não importa se o segundo retorno é 404 ou 200, o estado do servidor não mudou, então estou feliz com isso.
precisa
46

Idempotent é sobre o efeito da solicitação, não sobre o código de resposta que você obtém.

http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.2 diz:

Os métodos também podem ter a propriedade "idempotência", pois (além de problemas de erro ou expiração) os efeitos colaterais de N> 0 pedidos idênticos são os mesmos que para um único pedido.

Embora você possa obter um código de resposta diferente, o efeito do envio de solicitações N + 1 DELETE para o mesmo recurso pode ser considerado o mesmo.

Bruno
fonte
13

A distinção importante é que idempotente se refere a efeitos colaterais , não a todos os efeitos ou respostas. Se você fizer DELETE http://example.com/account/123isso, o efeito é que a conta 123 agora é excluída do servidor. Esse é o único efeito, o único e único muda para o estado do servidor. Agora, digamos que você faça a mesma DELETE http://example.com/account/123solicitação novamente, o servidor responderá de maneira diferente, mas seu estado é o mesmo.

Não é como a solicitação DELETE decidiu alterar o estado do servidor de uma maneira diferente, porque a conta estava ausente, como remover outra conta ou deixar um log de erros. Não, você pode chamar a mesma solicitação DELETE um milhão de vezes e pode ter certeza de que o servidor está no mesmo estado em que estava na primeira vez em que você o chamou .

Janac Meena
fonte
7

No RFC HTTP :

Os métodos também podem ter a propriedade "idempotência", pois (além de problemas de erro ou expiração) os efeitos colaterais de N> 0 pedidos idênticos são os mesmos que para um único pedido.

Note que são "efeitos colaterais", não "resposta".

fumanchu
fonte
7

Sim. Independentemente do código de resposta.

Da mais recente RFC para HTTP 1.1 (ênfase minha):

Os métodos idempotentes são diferenciados porque a solicitação pode ser repetida automaticamente se ocorrer uma falha na comunicação antes que o cliente possa ler a resposta do servidor. Por exemplo, se um cliente enviar uma solicitação PUT e a conexão subjacente for fechada antes que qualquer resposta seja recebida, o cliente poderá estabelecer uma nova conexão e tentar novamente a solicitação idempotente. Ele sabe que a repetição da solicitação terá o mesmo efeito pretendido, mesmo que a solicitação original tenha sido bem-sucedida, embora a resposta possa ser diferente.

Diz explicitamente que a resposta pode ser diferente. Mais importante, ele aponta a razão do conceito: se uma ação é idempotente, o cliente pode repetir a ação quando encontrar algum erro e sabe que não irá travar nada ao fazê-lo; caso contrário, o cliente precisará fazer uma consulta adicional (possivelmente GET) para verificar se a anterior é eficaz, antes de repetir a ação com segurança. Enquanto o servidor puder fazer essa garantia, a ação será idempotente. Citação de outro comentário :

A idempotência da computação é sobre a robustez de um sistema. Como as coisas podem falhar (por exemplo, falta de rede), quando uma falha é detectada, como você se recupera? A recuperação mais fácil é apenas fazê-lo novamente, mas isso só funciona se fazê-lo novamente for idempotente. Por exemplo, discard(x)é idempotente, mas pop()não é. É tudo sobre recuperação de erros.

Franklin Yu
fonte
2

Eu acho que a mesma coisa, 404 - Conta não existe.

Você poderia argumentar que 400 - Bad Request. Mas, no sentido de REST, o objeto no qual você solicitou a execução de uma ação não existe. Isso se traduz em 404.

Jason McCreary
fonte
1
Para gerar um 400, você precisaria saber que o objeto existia, o que é muito inquieto.
Annakata
1
@annakata, 400 nem sequer é para os recursos que existiam (talvez você tenha o 410 / Gone em mente), é para solicitações ruins "A solicitação não pôde ser entendida pelo servidor devido à sintaxe malformada."
de Bruno
3
@Bruno - Estou ciente do que isso significa, o OP citou.
Annakata
1
Eu acho que 200 ficaria bem. Você deseja que o estado do servidor seja que a conta se foi. Importa qual solicitação realmente a fez desaparecer? Ele ainda foi executado na segunda solicitação, o estado do servidor não mudou.
Andy
2

Citado na minha outra resposta aqui :

Historicamente, o RFC 2616, publicado em 1999, era as especificações HTTP 1.1 mais referenciadas. Infelizmente, sua descrição sobre a idempotência foi vaga , o que deixa espaço para todos esses debates. Mas essas especificações foram substituídas pela RFC 7231. Citado na RFC 7231, seção 4.2.2 Métodos Idempotentes , ênfase minha:

Um método de solicitação é considerado "idempotente" se o EFEITO NO SERVIDOR pretendido de várias solicitações idênticas com esse método for o mesmo que o efeito de uma única solicitação. Dos métodos de solicitação definidos por esta especificação, PUT, DELETE e métodos de solicitação seguros são idempotentes .

Portanto, está escrito nas especificações, idempotency tem tudo a ver com o efeito no servidor. O primeiro DELETE retornando um 204 e o subsequente DELETE retornando 404, esse código de status diferente NÃO torna o DELETE não idempotente. Usar esse argumento para justificar um retorno 204 subsequente é simplesmente irrelevante.


OK, então não se trata de idempotência. Mas então uma pergunta de acompanhamento pode ser: e se ainda optarmos por usar o 204 no DELETE subsequente? Tudo bem?

Boa pergunta. A motivação é compreensível: permitir que o cliente ainda atinja o resultado pretendido, sem se preocupar com o tratamento de erros. Eu diria que retornar 204 no subsequente DELETE é uma "mentira branca" do lado do servidor amplamente inofensiva, que o lado do cliente não notará imediatamente a diferença. É por isso que existem pessoas fazendo isso na natureza e ainda funciona. Lembre-se de que essa mentira pode ser considerada semanticamente estranha, porque "GET / inexistente" retorna 404, mas "DELETE / inexistente" fornece 204; nesse momento, o cliente descobriria que seu serviço não está totalmente em conformidade com seção 6.5.4 404 não encontrado .

Mas então, a maneira pretendida sugerida pela RFC 7231, ou seja, retornando 404 no DELETE subsequente, não deve ser um problema em primeiro lugar. Muitos outros desenvolvedores escolheram fazer isso. Isso é presumivelmente porque, qualquer cliente que implemente HTTP DELETE (ou qualquer método HTTP, nesse caso), não assumirá cegamente que o resultado sempre será bem-sucedido 2xx. E então, assim que o desenvolvedor começar a considerar o tratamento de erros, o 404 Not Found seria um dos primeiros erros a serem lembrados. Nesse ponto, ele / ela esperava concluir que, é semanticamente seguro para uma operação HTTP DELETE ignorar um erro 404. Problema resolvido.

RayLuo
fonte