Temos um URL no seguinte formato
/ instance / {instanceType} / {instanceId}
Você pode chamá-lo com os métodos HTTP padrão: POST, GET, DELETE, PUT. No entanto, existem mais algumas ações que realizamos, como "Salvar como rascunho" ou "Organizar"
Pensamos que poderíamos usar métodos HTTP personalizados, como: DRAFT, VALIDATE, CURATE
Eu acho que isso é aceitável, já que os padrões dizem
"O conjunto de métodos comuns para HTTP / 1.1 está definido abaixo. Embora esse conjunto possa ser expandido, não se pode presumir que métodos adicionais compartilhem a mesma semântica para clientes e servidores estendidos separadamente".
E ferramentas como o WebDav criam algumas de suas próprias extensões.
Existem problemas nos quais alguém se deparou com métodos personalizados? Estou pensando em servidores proxy e firewalls, mas qualquer outra área de preocupação é bem-vinda. Devo permanecer no lado seguro e ter apenas um parâmetro de URL como action = validate | curate | draft?
Respostas:
Uma das restrições fundamentais do HTTP e o recurso de design central do REST é uma interface uniforme fornecida por (entre outras coisas) um pequeno conjunto fixo de métodos que se aplica universalmente a todos os recursos. A restrição de interface uniforme tem várias vantagens e desvantagens. Estou citando liberalmente aqui Fielding .
Uma interface uniforme:
Por outro lado, uma interface uniforme:
As compensações são "projetadas para o caso comum da Web" e permitiram a construção de um grande ecossistema que fornece soluções para muitos dos problemas comuns nas arquiteturas da Web. A adesão a uma interface uniforme permitirá que seu sistema se beneficie desse ecossistema ao quebrá-lo, tornando-o difícil. Você pode querer usar um balanceador de carga como o nginx, mas agora só pode usar um balanceador de carga que entenda DRAFT e CURATE. Você pode querer usar uma camada de cache HTTP como o Varnish, mas agora só pode usar uma camada de cache HTTP que entenda DRAFT e CURATE. Convém pedir ajuda a alguém para solucionar uma falha do servidor, mas ninguém mais conhece a semântica de uma solicitação CURATE. Pode ser difícil alterar as bibliotecas preferidas de cliente ou servidor para entender e implementar corretamente os novos métodos. E assim por diante.
A maneira correta * de representar isso é como uma transformação de estado no recurso (ou recursos relacionados). Você não esboça uma postagem, transforma seu
draft
estadotrue
ou cria umdraft
recurso que contém as alterações e os links para as versões de rascunho anteriores. Você não CURA uma postagem, transforma seucurated
estadotrue
ou cria umcuration
recurso que vincula a postagem ao usuário que a selecionou.* Corrija que segue mais de perto os princípios de arquitetura REST.
fonte
Eu preferiria projetá-los como sub-recursos, nos quais você executa uma solicitação POST.
Considere que você tem um recurso em
/instance/type/1
, gostaria que a representação desse recurso transmitisse alguns links para 'ações' que podem ser executadas no recurso, como/instance/type/1/draft
e/instance/type/1/curate
. No JSON, isso pode ser tão simples quanto:Isso permite que o cliente seja muito explícito sobre o que precisa acontecer, durante a solicitação POST para o link fornecido pelo
curate
membro. O recurso publicado lá pode incluir argumentos que detalham o evento que talvez infligisse uma transição de estado.Seguir a abordagem "ingênua" de mover-se entre os possíveis estados de um recurso tem a desvantagem de não capturar quais eventos levaram a essas transições.
As transições de estado geralmente ocorrem em resposta a eventos específicos, e eu prefiro capturá-los do que deixar que o cliente decida que algo está agora em um 'estado' específico. Também torna a validação muito mais difícil. Além disso, você não seria capaz de capturar nenhum 'argumento' a menos que os descrevesse no próprio estado. E então tudo fica nojento quando algum código altera aqueles sem transição de estado real e a validação necessária, e tudo rapidamente se torna uma bagunça.
fonte
/vms/some-id
retorna links para ações comoPOST /vms/some-id/restart
e usamos para determinar se as ações devem ser ativadas ou desativadas. Eu tenho uma relação de amor / ódio com HATEOAS :)Eu acho que o método HTTP personalizado é a melhor maneira de implementar ações de entidade. Adicionar a ação ao corpo da entidade (POST) não parece certo, não faz parte da sua entidade (embora o resultado possa ser salvo nela). Além disso, o uso dos proxies de métodos HTTP personalizados pode determinar suas ações sem a necessidade de analisar o corpo da entidade.
É como CRUD, você sempre desejaria implementá-las, mas também possui seu próprio conjunto de ações específico (por entidade). Realmente não vejo qual seria o problema de estendê-los.
Também @Rein Henrichs "Você não desenha uma postagem, transforma seu estado de rascunho em verdadeiro ou cria um recurso de rascunho" parece falso para mim. Uma
drafts
propriedade seria usada para salvar persistentemente o estado, não para fazer a transformação. Ações nem necessariamente resultam em um 'estado' ou são salvas em uma propriedade. Criar uma entidade separada para cada estado / transformação parece ainda mais confuso. Tente manter a mesma referência (URI) para a entidade.fonte