Idempotência em requisições HTTP
- #RESTful
- #REST
- #API Rest
A noção de idempotência vem da matemática. Multiplicar um número por zero é uma operação idempotente. 5 × 0 é zero, mas 5 × 0 × 0 também é zero. Depois de multiplicar um número por zero, você pode continuar multiplicando-o por zero indefinidamente e obter o mesmo resultado: 0.
A idempotência é uma propriedade importante de algumas operações HTTP que garante que a mesma operação pode ser executada várias vezes sem alterar o resultado final ou causar efeitos colaterais indesejados, independente do número de vezes que é chamada, isso é importante em situações em que uma operação pode ser executada várias vezes, como em caso de falha de rede ou retry automático de uma operação não concluída.
Safe Methods:
Os métodos de solicitação são considerados "seguros" se sua semântica definida for essencialmente somente leitura, ou seja, o cliente não solicita e não espera qualquer mudança de estado no servidor de origem como resultado de aplicar um método seguro a um recurso de destino. Da mesma forma, razoável não se espera que o uso de um método seguro cause qualquer dano, perda de propriedade ou carga incomum no servidor de origem.
Exemplos de métodos seguros:
GET → É usado para obter informações sobre um recurso em um servidor. Quando um cliente faz uma solicitação GET, ele espera receber informações sobre o recurso solicitado, mas não espera que a solicitação cause qualquer mudança de estado no servidor. Além disso, é razoável esperar que o uso do método GET não cause nenhum dano, perda de propriedade ou carga incomum no servidor de origem.
URL: <https://api.exemplo.com/usuarios/123>
Método: GET
Status de Resposta: 200 OK
Conteúdo JSON da Resposta:
{
"id": 123,
"nome": "João Silva",
"email": "joao.silva@exemplo.com",
"idade": 35,
"cidade": "Rio de Janeiro"
}
HEAD → É usado para obter apenas os cabeçalhos de uma resposta HTTP, permitindo que o cliente verifique informações como o código de status, os cabeçalhos de resposta e a data da última modificação de um recurso. Ex: Um cliente pode enviar uma solicitação HEAD para um recurso de imagem para verificar seu tamanho, tipo de conteúdo e data da última modificação, sem receber o próprio conteúdo da imagem.
HEAD /downloads/video1.mpeg HTTP/1.0
OPTIONS →É usado para obter informações sobre as opções de comunicação disponíveis para um determinado recurso ou servidor. Ele retorna os métodos HTTP suportados pelo servidor, cabeçalhos permitidos, entre outras informações relevantes. Ex: Um cliente pode enviar uma solicitação OPTIONS para um servidor de API REST para descobrir quais métodos são permitidos para um determinado recurso, como GET, POST, PUT ou DELETE.
OPTIONS /download.php
Outros métodos idempotêntes:
DELETE → Obviamente não é um método seguro (Safe Method), porém enviar uma solicitação DELETE é muito diferente de não enviar uma solicitação DELETE. Mas o método DELETE tem outra propriedade muito importante: Ele é idempotente. Depois de excluir um recurso, ele desaparece. O estado do recurso mudou permanentemente. Você pode enviar outra solicitação DELETE e você pode obter um erro 404, mas o estado do recurso é exatamente como era após o primeiro pedido. O recurso ainda está desaparecido. Isso é idempotência. Enviar uma solicitação duas vezes tem o mesmo efeito no estado do recurso que enviá-la uma vez. A idempotência é um recurso útil, porque a Internet não é uma rede confiável. Suponha você envia uma solicitação DELETE e sua conexão atinge o tempo limite. Você nunca obteve uma resposta, então você não sabe se o DELETE passou. Você pode simplesmente enviar essa solicitação DELETE novamente e continue tentando até obter uma resposta. Nada extra acontecerá se um DELETE passa duas vezes em vez de uma vez. HTTP DELETE efetivamente multiplica um recurso por zero. Multiplicar por 1 é uma operação segura, da mesma forma que o HTTP GET deve ser seguro. Você pode multiplique um número por 1 durante todo o dia e nada mudará. Toda operação segura é também idempotente.
URL: <https://api.exemplo.com/usuarios/123>
Método: DELETE
PUT → PUT é idempotente, assim como DELETE. Se você enviar a mesma solicitação PUT 10 vezes, o resultado é o mesmo como se você tivesse enviado apenas uma vez. O cliente também pode usar PUT para criar um novo recurso, se souber a URL onde o novo recurso deve viver.
URL: <https://api.example.com/usuarios/123>
Método: PUT
Conteúdo JSON da solicitação:
{
"nome": "John Doe",
"email": "johndoe@example.com",
"idade": 30
}
Observe que PUT é uma operação idempotente mesmo quando você o usa para criar um novo recurso. Se enviar essa solicitação PUT cinco vezes, ela não será criada cinco postagens com o mesmo texto (da mesma forma que cinco solicitações POST podem).
Como a definição de seguro, a propriedade idempotente só se aplica a o que foi solicitado pelo usuário. Um servidor é livre para registrar cada um separadamente, reter um histórico de controle de revisão ou implementar outros efeitos colaterais não idempotentes para cada solicitação idempotente.
Métodos idempotentes são diferenciados porque a requisição pode ser repetida automaticamente se ocorrer uma falha de comunicação antes do cliente ser capaz de ler a resposta do servidor.
Para garantir que as operações na API sejam idempotentes, é importante que os recursos e endpoints sejam projetados de maneira apropriada, por exemplo, com o uso de identificadores únicos de recursos, como IDs, e o gerenciamento de transações e commits adequados. Isso ajuda a garantir que as operações possam ser executadas várias vezes sem causar problemas indesejados, como a criação de recursos duplicados ou inconsistências de dados.
E Quanto ao método POST e PATCH?
O método POST é não idempotente, pois cada chamada cria um novo recurso com um identificador único. Se um cliente enviar várias solicitações POST com os mesmos dados, serão criados vários recursos diferentes no servidor.
O método POST é não seguro, pois cria um novo recurso no servidor. A criação desse recurso pode ter efeitos colaterais, como enviar notificações, acionar processos de negócios, registrar informações no servidor, entre outros.
O método PATCH é usado para fazer atualizações parciais em um recurso existente. Em vez de substituir completamente o recurso, o PATCH permite que apenas as alterações específicas sejam aplicadas. No entanto, o método PATCH não é idempotente nem seguro.
URL: <https://api.exemplo.com/usuarios/123>
Método: PATCH
Conteúdo JSON da solicitação:
{
"idade": 25
}
Nesse exemplo, a solicitação PATCH é usada para adicionar um campo "idade" a um usuário existente. Se o campo "idade" já estiver presente, a chamada PATCH adicionará um novo valor ao campo. Cada chamada PATCH subsequente com o mesmo conteúdo JSON resultará em alterações adicionais no campo "age" do recurso.
Um método não idempotente é aquele em que a execução repetida da mesma operação pode ter efeitos diferentes no servidor. Cada chamada adicional a um método não idempotente pode resultar em alterações de estado ou efeitos colaterais diferentes. Portanto, a mesma solicitação enviada várias vezes pode levar a resultados diferentes.
Um método não seguro é aquele que pode causar alterações no estado do servidor ou ter efeitos colaterais indesejados. Enquanto um método seguro é apenas leitura e não deve causar alterações, um método não seguro pode alterar o estado do servidor ou executar ações que afetam o ambiente.
Portanto, métodos não idempotentes e não seguros, como POST e PATCH, podem ter efeitos diferentes em cada chamada adicional e podem causar alterações no estado do servidor ou efeitos colaterais indesejados.
RFC ft-ietf-httpbis-p2-semantics: Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content
Livro:
Amundsen, Mike Richardson, Leonard Ruby, Sam - RESTful Web APIs-O'Reilly Media (2015)