Qual verbo HTTP devo usar para acionar uma ação em um serviço da web REST?


81

Estou implementando um serviço web RESTful e uma das ações disponíveis será reload. Será usado para recarregar configurações, cache, etc.

Começamos com um GETURI simples como este: ${path}/cache/reload(nenhum parâmetro é passado, apenas o URI é chamado). Estou ciente de que os dados não devem ser modificados com uma solicitação GET.

Qual é o verbo correto a ser usado para chamar uma ação / comando em um serviço da web RESTful?

O recarregamento é um comando do serviço da web REST que recarrega seu próprio cache / configuração / etc. Não é um método que retorna informações ao cliente.

Provavelmente o que estou tentando fazer não é o REST, mas ainda é algo que precisa ser feito dessa maneira. O reloadmétodo era apenas um exemplo real que faz sentido no escopo do aplicativo e com a maioria das respostas focadas nele, mas, na verdade, eu só precisava saber qual verbo acionar uma ação que não faz CRUD, mas ainda altera os dados / Estado.

Encontrei esta resposta detalhada no Stack Overflow sobre o assunto: https://stackoverflow.com/questions/16877968/


1
"Recarregando" é a sensação de um aplicativo atualizar os dados que serão exibidos? Existe alguma diferença entre recarregar e obter os dados novamente?
Sean Redmond

1
@SeanRedmond Não, os dados não são enviados ao cliente. De fato, o cliente está dizendo ao serviço da web REST para executar um comando interno (recarregar). Algo como: "muitas configurações foram alteradas no banco de dados, portanto, o serviço web REST, recarregue-as agora na sua memória".
Renato Dinhani

Duplicação entre sites: stackoverflow.com/q/15340946/319403
cHao 2/14

Você já pensou em usar um parâmetro de cabeçalho em solicitações apropriadas? Isso parece muito com uma atualização de cache ...
Guran 17/03

Respostas:


25

Eu não acho que exista um verbo adequado para essa ação, porque essa transação não é realmente "RESTful". O "s" e "t" significam "transferência de estado" e nada está sendo transferido aqui. Ou, dito de outra maneira, pela definição mais estrita, os verbos como PUT e POST são sempre usados ​​com um substantivo e "recarregar" apenas possui o verbo.

Essa recarga pode não ser RESTful, mas ainda pode ser útil e você terá apenas uma maneira de fazer isso e conviver ou explicar que é incomum. GET é provavelmente o mais simples. Porém, há bastante ceticismo nos comentários; portanto, você deve pensar se essa ação de recarregamento é necessária ou não, porque outra coisa não está fazendo exatamente o que deveria estar fazendo.


Concordo que isso não é RESTful, mas pode ser útil. Eu acho que você deveria aconselhar um PUT, porque isso provavelmente é idempotente, mas não nulo.
Aaron Greenwald

@ Aaron, a comparação entre idempotente e nullimpotent é muito boa, mas como você determina quando não é importante?
30715 Craig

@ Craig é idempotente se executá-lo muitas vezes tiver o mesmo efeito de executá-lo uma vez. É nulipotente se executá-lo uma ou várias vezes tiver o mesmo efeito no servidor que executá-lo zero vezes. en.wikipedia.org/wiki/Idempotence
Aaron Greenwald

5
@AaronGreenwald “notimpotent” [não-im-poht-nt] [não-im-pawr-tnt] - adjetivo - 1. Um jogo de palavras, “não importante”, antônimo do adjetivo “importante”. 2. Humor… ;-)
Craig

@ Craig eu perdi completamente que :)
Aaron Greenwald

75

Se você deseja ser RESTful, não pense no verbo para executar uma ação, pense no estado em que deseja que o recurso esteja depois que o cliente tiver feito algo.

Portanto, usando um de seus exemplos acima, você tem uma fila de e-mails que está enviando e-mails. Você deseja que o cliente coloque essa fila de emails no estado de pausa ou parada ou algo assim.

Portanto, o cliente coloca um novo estado no servidor para esse recurso. Pode ser tão simples quanto esse JSON

PUT http://myserver.com/services/email_service HTTP/1.1
Content-Type: text/json

{"status":"paused"}

O servidor descobre como passar do status atual (por exemplo, "em execução") para o status / estado "em pausa".

Se o cliente fizer um GET no recurso, ele retornará o estado em que está atualmente (diga "pausado").

O motivo para fazê-lo dessa maneira e por que o REST pode ser tão poderoso é que você deixa o COMO chegar a esse estado no servidor.

O cliente apenas diz "Este é o estado em que você deve estar agora" e o servidor descobre como conseguir isso. Pode ser um simples golpe em um banco de dados. Pode exigir milhares de ações. O cliente não se importa e não precisa saber.

Assim, você pode reescrever / reprojetar completamente como o servidor faz isso e o cliente não se importa. O cliente precisa apenas estar ciente dos diferentes estados (e suas representações) de um recurso, não de nenhum dos internos.


2
Para mim, esta é a resposta correta. Atualizar dados no servidor não é uma operação idempotente e GETé um verbo completamente inapropriado para uso. PUTé o verbo mais apropriado, pois a operação pode ser considerada como a atualização do "status recarregado" do cache para "recarregado".
Jez

@ Jez Das respostas aqui, eu prefiro este também. Seguindo a metáfora do e-mail, de imediato, é estranho pensar em enviar o e-mail colocando-o no estado "envio" em vez de apenas enviá- lo (uma ação). Mas se você pensar sobre isso, é realmente a mesma coisa que colocá-lo na "caixa de saída". De fato, o próprio sistema de correio provavelmente está na fila interna dessa maneira quando você solicita o envio. Portanto, a API permite que você coloque o email no estado "envio", e a API não é obrigada a se explicar além disso.
30715 Craig

Portanto, por extensão, se você não quiser que a mensagem seja enviada ainda, coloque-a no estado "agendado" com uma data / hora em que deve ser liberada. Se não estiver completo, coloque-o (ou está implicitamente / por padrão) no estado "rascunho" etc.
Craig

... embora eu ache que prefiro POST a PUT neste caso, já que PUT também deve ser idempotente, mas o POST não tem essa restrição.
30715 Craig

1
Você poderia fazer isso, mas no final das contas, ele está tentando encaixar um pino quadrado em um buraco redondo. Não há razão para que o cliente precise acionar o servidor para "recarregar" qualquer coisa, isso é apenas um projeto arquitetônico ruim. O servidor pode atualizar seu estado interno em cada chamada ou em um intervalo de tempo fixo. Depender do cliente para solicitar ao servidor que recarregue algo independente de qualquer solicitação real de um estado de recurso não é uma arquitetura RESTful.
Cormac Mulhall

32

Algumas das outras respostas, incluindo a aceita, aconselham você a usar um GET (embora não com muito entusiasmo).

Discordo.

Primeiro de tudo, todos os outros dizendo que isso não é o ideal e que realmente não são RESTful estão corretos. Em um cenário RESTful adequado, você está manipulando recursos no servidor e adicionando, atualizando, excluindo, recuperando etc. esses recursos. Uma PUT deve enviar uma carga útil que represente qual deve ser o recurso quando a solicitação for concluída e o POST deve enviar uma carga útil que represente um recurso a ser adicionado ao servidor. E um GET deve retornar um recurso no servidor.

Você tem um RPC (chamada de procedimento remoto), que não é RESTful - você deseja fazer algo no servidor. Portanto, se você estiver tentando criar uma API puramente RESTful, reconsidere o que está fazendo.

Dito isto, às vezes você precisa dobrar um pouco as regras. Especialmente se você estiver desenvolvendo uma API interna que não será exposta ao público, você pode decidir que a troca vale a pena.

Se o fizer, eu recomendaria um PUT ou POST, dependendo se o RPC é ou não idempotente .

Em geral, dizemos que HTTP PUT mapeia para SQL UPDATE e que HTTP POST mapeia para SQL INSERT, mas isso não é rigorosamente verdade. Uma maneira mais pura de afirmar que o HTTP PUT deve ser idempotente e o HTTP POST não precisa. Isso significa que você pode chamar a mesma solicitação PUT quantas vezes quiser, sem efeitos colaterais. Depois de ligar uma vez, é inofensivo chamá-lo novamente. Mas você não deve chamar repetidamente solicitações de POST, a menos que queira - cada POST altere os dados no servidor novamente.

No seu caso, se você precisar ter essa função de recarga, recomendo um PUT porque parece idempotente. Mas eu ainda insistiria que você considerasse o que os outros disseram sobre não precisar disso.


6

POSTe PUTsão os verbos HTTP usados ​​para enviar uma entidade para um servidor web. Com PUT, a entidade enviada é a (nova) representação do recurso no URI fornecido, que não se encaixa no que você deseja. POSTé para o manipulador de formulários tradicional, onde a entidade é dados auxiliares do recurso, então esse é o vencedor. A entidade incluiria o comando ou ação (por exemplo, "action = reload").

Dito isto, o comando em questão provavelmente não deve ser exposto por meio de uma interface REST. Parece que a necessidade de "recarregar" surge porque os dados podem ser alterados por outro canal (por exemplo, sistema de arquivos, cliente DB). Os caches devem ser transparentes. Além disso, as solicitações HTTP devem ser atômicas, levando em consideração as mensagens enviadas por outros canais. Oferecer um comando "recarregar" para definições de configuração parece uma complexidade desnecessária; exigindo que seja um design quebradiço. Expor "recarregar" para limpeza após uma atualização por outro canal está sujo, porque um canal não contém a conversa inteira. Em vez disso, considere um dos seguintes:

  • fazendo atualizações inteiramente via REST
  • expondo o (s) comando (s) para o outro canal
  • automatizando as ações

Algumas dessas opções podem não ser viáveis, dependendo de outras restrições.

Consulte também " PUT vs POST no REST ".


Obrigado. Eu removi o "interno" da edição porque, na verdade, o método "recarregar" deve ser público. Eu apenas tentei dizer que se refere ao serviço da web em si. Eu acho que postar a "ação" seria uma boa abordagem.
Renato Dinhani

@ RenatoDinhaniConceição: mesmo sem o "interno", ele ainda cheira. Pode ser que você faça uma nova pergunta sobre se o design é bom.
out

4

Eu argumentaria por que uma solicitação de cliente precisaria explicitamente fazer uma chamada para atualizar algo assim. Parece que isso deve ser uma lógica oculta em uma implementação mais típica do GET (ou seja, puxar dados, mas o serviço atualiza os dados antes de serem puxados) ou por outro gatilho no back-end do cliente.

Afinal, os dados / configuração precisariam estar atualizados apenas nas chamadas subseqüentes, portanto, eu me inclinaria mais para uma chamada preguiçosa ou ansiosa por uma atualização de dados. Obviamente, estou assumindo muito aqui, mas eu daria um passo para trás para reavaliar a necessidade de uma ligação tão explícita e independente.


Olhe para a minha edição. "reload" não é um comando que retorna dados. Refere-se ao próprio serviço da web REST. Em termos gerais, minha pergunta se refere a ações de acionamento em um serviço web REST. Outro exemplo pode ser: email_queue/stop_sending_emails. Estou apenas dando um comando para algo usando uma interface RESTful.
Renato Dinhani

5
Eu ainda concordo. Invocar o SIGHUP em um processo local faz sentido, pois o computador deve confiar em alguém conectado localmente que tenha acesso a esse sinal. Mas para um protocolo sem estado, acessível pela Internet? Talvez o serviço da Web deva recarregar automaticamente conforme necessário por meio de pesquisa ou monitoramento de arquivos. Essa chamada deve ser completamente desnecessária.

1
Concordo. Coisas como configuração e armazenamento em cache devem ser transparentes para o cliente. Talvez você deva nos dar uma descrição mais concreta de uma situação na qual seu endpoint seria chamado.
Benjamin Hodgson

3

Por que não tratar a ação como um recurso. Portanto, como você deseja atualizar o cache, você POSTARIA uma nova ação em seu sistema.

Para os puristas, você pode ter um URL dedicado para isso. Observe que você pode estender isso e registrar as ações reais em um banco de dados (ou qualquer armazenamento) com data, status, usuário, etc ... Apenas meus pensamentos aqui.

Operação / ações genéricas em todo o sistema / {action}

Operação específica para um tipo de recurso / ações / {recurso} / {ação}

Operação específica para um recurso / ações / {recurso} / {id} / {ação}

No seu caso, o cache provavelmente é de todo o sistema / actions / reload_cache


0

Qual verbo HTTP devo usar para acionar uma ação em um serviço da web REST?

Ao considerar os detalhes de um serviço REST, geralmente é útil considerar esta heurística: como você implementaria isso em um site?

O HTML pode descrever apenas solicitações GET e POST de forma nativa. Então, podemos começar a procurar lá.

É GETapropriado? Para responder a essa pergunta, precisamos pensar nas suposições que clientes e componentes intermediários podem fazer GET. A semântica de GETsão seguros

o cliente não solicita e não espera nenhuma alteração de estado no servidor de origem como resultado da aplicação de um método seguro a um recurso de destino. Da mesma forma, não se espera que o uso razoável de um método seguro cause danos, perda de propriedade ou carga incomum no servidor de origem.

A implicação, portanto, é que os clientes e os componentes intermediários têm o poder de chamar uma solicitação GET com a frequência necessária para satisfazer suas próprias preocupações. As aranhas podem obter recursos indiscriminadamente para atualizar seus índices. Os caches podem ser pré-buscados. Em uma rede não confiável, as mensagens perdidas podem ser repetidas com a frequência necessária para garantir pelo menos uma resposta.

Será usado para recarregar configurações, cache, etc.

Se essas coisas são caras, talvez você não queira que os clientes enviem essas solicitações a seu critério.

POST, por outro lado, é efetivamente irrestrito - isso reduz bastante as suposições que os clientes genéricos podem fazer. Você não obtém componentes que fazem solicitações POST especulativas porque eles seriam defeituosos - nada no padrão diz que está tudo bem.

PUT, PATCH, DELETE... estes são métodos inseguros com a semântica mais específicos do que POST; se eles são ou não apropriados, dependerá do seu modelo de recursos.

Uma idéia importante a ser lembrada é que os métodos HTTP pertencem ao domínio do documento (consulte a palestra de Jim Webber, 2011 ). Os efeitos que você está descrevendo provavelmente não fazem parte do domínio do documento, mas são efeitos colaterais invocados quando os documentos são alterados. . Isso lhe dá muita liberdade em termos de como você organiza seus documentos para realizar o trabalho.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.