Como criar URLs REST sem verbos?

283

Estou lutando para determinar como criar URLs tranqüilos. Sou a favor da abordagem tranqüila de usar URLs com substantivos e não verbos que não entendem como fazer isso.

Estamos criando um serviço para implementar uma calculadora financeira. A calculadora usa vários parâmetros que enviaremos por meio de um arquivo CSV. Os casos de uso envolveriam:

  1. Carregar novos parâmetros
  2. Obtenha os parâmetros mais recentes
  3. Obter parâmetros para uma determinada data comercial
  4. Ativar um conjunto de parâmetros
  5. Validar um conjunto de parâmetros

Eu acho que a abordagem tranqüila seria ter os seguintes URLs de tipo:

/parameters
/parameters/12-23-2009

Você pode alcançar os três primeiros casos de uso com:

  1. POST em que você inclui o arquivo de parâmetro na solicitação de postagem
  2. GET do primeiro URL
  3. GET do segundo URL

Mas como você faz o 4º e o 5º caso de uso sem um verbo? Você não precisaria de URLs como:

/parameters/ID/activate
/parameters/ID/validate

??

Marcus Leon
fonte
3
Prefiro PATCH do que POST para atualização parcial.
user2016971

Respostas:

71

Talvez algo como:

PUT /parameters/activation HTTP/1.1
Content-Type: application/json; encoding=UTF-8
Content-Length: 18

{ "active": true }
yfeldblum
fonte
1
POSTestá OK se você precisar executar um "procedimento", como verificar os parâmetros sempre que enviar uma solicitação. Mas quando você modifica o estado (aplicativo) do recurso, atualiza o recurso existente, não cria um novo recurso ou lança uma solicitação de processamento.
Andrey Vlasovskikh 24/10/09
19
PUT é para criar um novo recurso ou colocar (no todo, não em parte) um novo recurso em um URL específico. Não vejo como o PUT se encaixa nesse caso.
24509 Breton
30
Na verdade, POSTvs PUTnão é exatamente como insertvs update. PUTatualiza o recurso correspondente ao caminho especificado ou cria um novo recurso correspondente ao caminho especificado. POSTcria um novo recurso em algum lugar. Por exemplo, PUT /blog/posts/3/comments/5atualizará o comentário apropriado, enquanto POST /blog/posts/3/commentscriará um novo commentrecurso (e deve retornar o caminho para o novo recurso na resposta).
Yfeldblum 24/10/2009
23
@Justice @Breton A diferença mais importante é que PUTé idempotente enquanto POSTnão é. Normalmente, você deve colocar o máximo de restrições sobre o que fornecer como resultado possível. Ficar com PUTfornece mais informações ao cliente do serviço.
Andrey Vlasovskikh 24/10/09
3
O recurso também poderia ter sido / parameters / status e o corpo da solicitação poderia ter sido apenas "ativo". Dessa forma, você está colocando um recurso totalmente novo em um URL específico.
Carlos Aguayo
991

Princípios gerais para um bom design de URI:

  • Não use parâmetros de consulta para alterar o estado
  • Não use caminhos de maiúsculas e minúsculas se puder ajudá-lo; minúsculas é melhor
  • Não use extensões específicas da implementação em seus URIs (.php, .py, .pl, etc.)
  • Não caia no RPC com seus URIs
  • Não limitar o seu espaço URI, tanto quanto possível
  • Do segmentos de caminho keep curto
  • Do preferem quer /resourceou /resource/; crie 301 redirecionamentos daquele que você não usa
  • Fazer parâmetros de consulta uso de sub-seleção de um recurso; ou seja, paginação, consultas de pesquisa
  • Do material movimento fora da URI que deve estar em um corpo HTTP cabeçalho ou um

(Nota: eu não disse "design de URI RESTful"; os URIs são essencialmente opacos no REST.)

Princípios gerais para a escolha do método HTTP:

  • Não nunca usar GET para estado alter; essa é uma ótima maneira de o Googlebot estragar o seu dia
  • Não use PUT, a menos que esteja atualizando um recurso inteiro
  • Não use PUT, a menos que você também possa legitimamente fazer um GET no mesmo URI
  • Não use o POST para recuperar informações de longa duração ou que possam ser razoáveis ​​para armazenar em cache
  • Não execute uma operação que não seja idempotente com PUT
  • Fazer uso GET para, tanto quanto possível
  • Fazer uso POST em detrimento de PUT quando em dúvida
  • Fazer uso POST sempre que você tem que fazer algo que se sente RPC-like
  • Fazer uso PUT para as classes de recursos que são maiores ou hierárquica
  • Não utilize DELETE em detrimento de POST aos recursos remove
  • Do uso GET para coisas como cálculos, a menos que a sua entrada é grande, em que POST caso de uso

Princípios gerais de design de serviços da web com HTTP:

  • Não coloque metadados no corpo de uma resposta que deve estar em um cabeçalho
  • Não coloque metadados em um recurso separado, a menos que incluí-lo criaria uma sobrecarga significativa
  • Não utilizar o código de status adequado
    • 201 Createddepois de criar um recurso; O recurso deve existir no momento em que a resposta é enviada
    • 202 Accepted depois de executar uma operação com sucesso ou criar um recurso de forma assíncrona
    • 400 Bad Requestquando alguém faz uma operação com dados que são claramente falsos; para sua aplicação, isso pode ser um erro de validação; geralmente reserva 500 para exceções não capturadas
    • 401 Unauthorizedquando alguém acessa sua API sem fornecer um Authorizationcabeçalho necessário ou quando as credenciais dentro da Authorizationsão inválidas; não use esse código de resposta se não estiver esperando credenciais por meio de um Authorizationcabeçalho.
    • 403 Forbidden quando alguém acessa sua API de uma maneira que possa ser maliciosa ou se não está autorizada
    • 405 Method Not Allowed quando alguém usa POST quando deveria ter usado PUT, etc
    • 413 Request Entity Too Large quando alguém tenta enviar para você um arquivo inaceitavelmente grande
    • 418 I'm a teapot ao tentar preparar café com um bule de chá
  • Fazer uso de cabeçalhos de cache sempre que puder
    • ETag cabeçalhos são bons quando você pode reduzir facilmente um recurso a um valor de hash
    • Last-Modified deve indicar a você que manter um registro de data e hora de quando os recursos são atualizados é uma boa ideia
    • Cache-Controle Expiresdevem receber valores sensatos
  • Faça o possível para honrar os cabeçalhos de cache em uma solicitação ( If-None-Modified, If-Modified-Since)
  • Do uso redirecionamentos quando eles fazem sentido, mas estes devem ser raro para um serviço web

Com relação à sua pergunta específica, o POST deve ser usado para os itens 4 e 5. Essas operações se enquadram na diretriz "semelhante a RPC" acima. Para o item 5, lembre-se de que o POST não precisa necessariamente ser usado Content-Type: application/x-www-form-urlencoded. Isso poderia facilmente ser uma carga útil JSON ou CSV.

Bob Aman
fonte
11
O 413 é voltado para o tamanho da solicitação que você está sendo enviado, para que você possa rejeitar educadamente alguém enviando informações sobre você, geralmente em conjunto com o 411, para forçar as pessoas a dizer quanto está sendo enviado. Para o exemplo dado contra 413, acho que 400 seria uma resposta mais apropriada.
Garry Shutler
5
+1, pois esse é um ótimo recurso. No entanto, é um recurso geral e não responde diretamente à pergunta. Idealmente, isso deve incluir um parágrafo adicional com uma resposta específica.
Samuel Neff
@GarryShutler Boa captura, você está absolutamente certo. Obrigado pela edição.
Bob Aman
1
Sim, você só usaria PUT nos casos em que estiver substituindo o objeto inteiro. No entanto, eu diria que PATCH ou POST são razoáveis ​​no caso de uma atualização parcial de um recurso. PATCH é mais claro em termos do que a operação vai fazer, mas como nem todos os clientes são capazes de emitir uma solicitação PATCH , é inteiramente apropriado permitir um POST , e eu posso até chegar ao ponto de advogar que um POST sempre deve ser permitido como substituto se PATCH for usado.
21813 Bob Aman
1
+1 para 409 erros. Um erro 400 é algo que pode ser resolvido com validação suficiente do lado do cliente. Um 409 esclarece que a solicitação em si era aceitável e consistente, mas entra em conflito com algum aspecto do estado do servidor (geralmente controles de simultaneidade, mas teoricamente qualquer restrição que não seja de entrada).
claytond
18

Sempre que parecer que você precisa de um novo verbo, pense em transformar esse verbo em um substantivo. Por exemplo, transforme 'ativar' em 'ativação' e 'validar' em 'validação'.

Mas, pelo que você escreveu, eu diria que seu aplicativo tem problemas muito maiores.

Sempre que um recurso chamado 'parâmetro' é proposto, ele deve enviar sinais vermelhos na mente de todos os membros da equipe do projeto. 'parâmetro' pode literalmente se aplicar a qualquer recurso; não é específico o suficiente.

O que exatamente um 'parâmetro' representa? Provavelmente várias coisas diferentes, cada uma das quais deve ter um recurso separado dedicado a ela.

Outra maneira de chegar a isso - quando você discute seu aplicativo com os usuários finais (aqueles que presumivelmente sabem pouco sobre programação), quais são as palavras que eles mesmos usam repetidamente?

Essas são as palavras pelas quais você deve projetar seu aplicativo.

Se você ainda não teve essa conversão com possíveis usuários - pare tudo agora e não escreva outra linha de código até conseguir! Somente então sua equipe terá uma idéia do que precisa ser construído.

Não sei nada sobre software financeiro, mas se eu tivesse que adivinhar, diria que alguns dos recursos podem ter nomes como "Relatório", "Pagamento", "Transferência" e "Moeda".

Há vários bons livros nessa parte do processo de design de software. Dois que posso recomendar são padrões de design e análise orientados a domínio .

Rich Apodaca
fonte
1
Este é realmente um bom ponto. É fácil perder se você estiver no estado de espírito para processar lógica e raciocínio formais. Não importa o que é X, desde que ele se encaixe com as outras partes de uma maneira válida. Fatores humanos simplesmente desaparecem.
Breton
1
Às vezes, acho útil converter as palavras em um "recurso de processamento", como "ativador" ou "validador". De acordo com a RFC 2616, o POST pode ser usado para "Fornecer um bloco de dados ... para um processo de manipulação de dados"
Darrel Miller
Entendido. Nesse caso, os usuários se referem aos dados como "parâmetros" (ou "parâmetros de risco" ou algo semelhante). A lista de parâmetros contém muitos tipos diferentes de configurações, mas os parâmetros são sempre carregados como um conjunto inteiro (em um arquivo CSV).
Marcus Leon
@ Marcus - isso soa como um caso muito incomum. Talvez se você explicasse o que seu aplicativo faz com mais detalhes, poderíamos oferecer sugestões melhores para identificar recursos.
25610 Rich Apodaca
1
"quando você discute seu aplicativo com os usuários finais, quais são as palavras que eles mesmos usam repetidamente?" ... e se todos forem verbos? XD
Amalgovinus
11

O design dos seus URLs não tem nada a ver com o fato de seu aplicativo ser RESTful ou não. A frase "URLs RESTful" é, portanto, um absurdo.

Eu acho que você deveria ler um pouco mais sobre o que realmente é o REST. O REST trata os URLS como opacos e, como tal, não sabe o que há neles, se existem verbos ou substantivos ou o que for. Você ainda pode criar seus URLs, mas isso é sobre a interface do usuário, não o REST.

Dito isso, vamos à sua pergunta: Os dois últimos casos não são RESTful e não se encaixam em nenhum tipo de esquema repousante. Isso é o que você pode chamar de RPC. Se você é sério sobre o REST, terá que repensar como o aplicativo funciona desde o início. Ou abandone o REST e apenas faça seu aplicativo como um aplicativo RPC.

Hrmmm talvez não.

A idéia aqui é que você deve tratar tudo como um recurso; portanto, uma vez que um conjunto de parâmetros tenha um URL, você pode se referir a ele, basta adicionar:

GET [parametersurl]/validationresults

POST [paramatersurl]
body: {command:"activate"}

Mas, novamente, essa coisa de ativação é RPC, não REST.

Bretão
fonte
Você afirma um ponto interessante aqui. Você pode detalhar um pouco mais como seria a abordagem RESTful para algo assim?
poezn
Passei um pouco de tempo lendo as respostas aqui e acho que a justiça pode estar ligada a algo. ele modela propriedades individuais do seu objeto de parâmetros como recursos individuais e usa o verbo PUT para substituir o conteúdo dessa propriedade nesse recurso. Isso está modelando o estado de cada objeto como uma coleção de recursos e modificando o estado como colocando ou removendo ou modificando o recurso. Quanto à validação - você só precisa de um recurso que declare magicamente se os parâmetros são válidos ou não, como acima na minha resposta. Isso seria bom, desde que isso não tenha efeitos colaterais.
24509 Breton
Desde que, claro, o que "Ativar" faça seja apenas definir uma propriedade como verdadeira. Se precisar fazer mais alguma coisa, ainda não é RESTful, e não tenho certeza de como você o modelaria.
24509 Breton
Eu não acho que você possa dizer que os dois últimos casos não são RESTful. Com efeito, Ativar e Validar são apenas maneiras indiretas de dizer que o recurso está mudando para um novo estado em uma máquina de estado. O REST é capaz de modelar isso.
Darrel Miller
@ Darrel, acho que você aponta uma parte do REST que pode ser um desafio para muitas pessoas que são novas no REST. Como você implementaria uma operação "Validar recurso x"? Acho que o difícil é que é uma operação que pode resultar em uma mudança de estado, mas o novo estado é resultado da solicitação feita.
Sean
6

Os requisitos de ativação e validação são situações em que você está tentando alterar o estado de um recurso. Não é diferente que fazer um pedido "concluído" ou alguma outra solicitação "enviada". Existem várias maneiras de modelar esses tipos de mudança de estado, mas uma que eu acho que geralmente funciona é criar recursos de coleção para recursos do mesmo estado e depois mover o recurso entre as coleções para afetar o estado.

por exemplo, crie alguns recursos como,

/ActiveParameters
/ValidatedParameters

Se você deseja ativar um conjunto de parâmetros, adicione-o à coleção ActiveParameters. Você pode passar o conjunto de parâmetros como um corpo de entidade ou um URL como parâmetro de consulta, da seguinte maneira:

POST /ActiveParameters?parameter=/Parameters/{Id}

O mesmo pode ser feito com os / ValidatedParameters. Se os parâmetros não forem válidos, o servidor poderá retornar "Solicitação incorreta" à solicitação para adicionar os parâmetros à coleção de parâmetros validados.

Darrel Miller
fonte
1

Eu sugeriria o seguinte recurso e métodos Meta.

Ative os parâmetros e / ou valide-os:

> PUT /parameters/<id>/meta HTTP/1.1
> Host: example.com
> Content-Type: application/json
> Connection: close
>
> {'active': true, 'require-valid': true}
>
< HTTP/1.1 200 OK
< Connection: close
<

Verifique se os parâmetros estão ativos e válidos:

> GET /parameters/<id>/meta HTTP/1.1
> Host: example.com
> Connection: close
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Connection: close
<
< {
<     'active': true,
<     'require-valid': true,
<     'valid': {'status': false, 'reason': '...'}
< }
<
Andrey Vlasovskikh
fonte
Pelo que entendi, a questão é sobre a nomeação dos URLs repousantes, não sobre a funcionalidade, não é?
24640 poezn
2
Uma pergunta confinada a "URLs RESTful" é uma pergunta ruim e não deve ser respondida. Em vez disso, a pergunta deve ser expandida para considerar "Recursos RESTful, com métodos e URLs associados" - e respondida como tal.
Yfeldblum 24/10/09
Pelo que entendi, a pergunta era sobre as convenções de nomenclatura de URL e os métodos HTTP aos quais o recurso nomeado deveria responder.
Andrey Vlasovskikh 24/10/09
1

Fico um pouco triste ao ver que, depois de mais de 10 anos, não há uma resposta realmente afirmando como uma coisa solicitada no OP poderia ser projetada em uma arquitetura REST; portanto, sinto a necessidade de fazer isso agora.

Primeiras coisas primeiro, o que é REST ?! O acrônimo REST ou ReST significa "Representational State Transfer" e define a troca do estado de um recurso em um determinado formato de representação. O formato de representação é maré para o tipo de mídia negociado. No caso deapplication/html formato de representação, pode haver um fluxo de conteúdo de texto formatado em HTML processado no navegador, provavelmente após a aplicação de alguma formatação de folha de estilo para posicionar certos elementos em determinados locais.

O REST é, em princípio, uma generalização da Web navegável que todos conhecemos, embora tenha como alvo todos os tipos de aplicativos e não apenas navegadores. Portanto, por design, os mesmos conceitos que se aplicam à Web também se aplicam a uma arquitetura REST. Uma pergunta como conseguir algo de uma maneira "RESTful" resolve responder à pergunta de como conseguir algo em uma página da Web e depois aplicar os mesmos conceitos na camada de aplicativo.

Uma calculadora baseada na Web geralmente pode começar com alguma "página" que permite inserir alguns valores para calcular antes de enviar os dados inseridos para o servidor. Em HTML, isso geralmente é alcançado por meio de <form>elementos HTML que ensinam um cliente sobre os parâmetros disponíveis para definir, o local de destino para o qual enviar a solicitação e o formato de representação a ser aplicado ao enviar os dados de entrada. Isto pode ser assim:

<html>
  <head>
    ...
  </head>
  <body>
    <form action="/../someResource" method="post" enctype="application/x-www-form-urlencoded">
      <label for="firstNumber">First number:</label>
      <input type="number" id="firstNumber" name="firstNumber"/>

      <label for="secondNumber">Second number:</label>
      <input type="number" id="secondNumber" name="secondNumber"/>

      <input type="submit" value="Add numbers"/>
    </form>
  </body>
</html>

A amostra acima, ou seja, afirma que existem dois campos de entrada que podem ser preenchidos pelo usuário ou por outros autômatos e que, ao chamar o elemento de entrada de envio, o navegador se encarrega de formatar os dados de entrada em um application/x-www-form-urlencodedformato de representação enviado para o local de destino mencionado por meio do método de solicitação HTTP especificado, POSTneste caso. Se entrarmos 1no firstNumbercampo de entrada e 2no secondNumbercampo de entrada, o navegador gerará uma representação firstNumber=1&secondNumber=2e a enviará como a carga útil do corpo da solicitação real para o recurso de destino.

A solicitação HTTP bruta emitida para o servidor pode ser assim:

POST /../someResource
Host: www.acme.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 28
Accept: application/html

firstNumber=1&secondNumber=2

O servidor pode executar o cálculo e responder com uma página HTML adicional que contém o resultado do cálculo, conforme a solicitação indicou que o cliente entende esse formato.

Como Breton já apontou, não existe URL ou URI "RESTful". Um URI / URL é seu próprio tipo de coisa e não deve transmitir nenhum significado a um cliente / usuário. Na amostra da calculadora acima, um usuário simplesmente não está interessado para onde enviar os dados, apenas está interessado em que, ao acionar o campo de entrada de envio, a solicitação é enviada. Todas as informações necessárias para executar a tarefa já devem ser fornecidas pelo servidor.

Um navegador também pode não estar ciente de que a solicitação está realmente alimentando uma calculadora com alguns parâmetros de entrada; também pode ser algum tipo de formulário de pedido que retorna apenas a próxima representação de formulário para continuar o processo de pedido ou algum tipo totalmente diferente de recurso. Ele simplesmente executa o que a especificação HTML exige nesse caso e não se importava com o que o servidor realmente está fazendo. Esse conceito permite que um navegador use o mesmo formato de representação para fazer todo tipo de coisa, como solicitar alguns itens da sua loja on-line preferida, conversar com seus melhores amigos, acessar uma conta on-line e assim por diante.

A disponibilidade de certos elementos, como no caso do campo de entrada de envio que geralmente é renderizado como botão, define o que você deve fazer com ele. No caso de um botão ou link, basicamente, você deve clicar nele. Outros elementos podem transmitir diferentes possibilidades. Essa disponibilidade também pode ser expressa por meio de relações de link, como por exemplo, com preloadlinks anotados que basicamente informam ao cliente que ele já pode carregar o conteúdo do recurso vinculado em segundo plano, pois o usuário provavelmente irá capturar esse conteúdo a seguir. É claro que essas relações de link devem ser padronizadas ou seguir o mecanismo de extensão dos tipos de relações, conforme definido pelos links da Web. .

Esse é o conceito fundamental usado na Web e que também deve ser usado em uma arquitetura REST. De acordo com o "tio Bob", Robert C. Martin, uma arquitetura tem a ver com intenção e a intenção por trás da arquitetura REST é a dissociação de clientes de servidores para permitir que os servidores evoluam livremente no futuro sem ter medo de prejudicar os clientes. Infelizmente, isso requer muita disciplina, pois é muito fácil introduzir acoplamentos ou adicionar soluções de correção rápida para concluir o trabalho e seguir em frente. Como Jim Webber apontou em uma arquitetura REST, você, como provedor de serviços, deve tentar criar um protocolo de aplicativo de domínio semelhante a um jogo de computador baseado em texto dos anos 70 que os clientes seguirão até chegarem ao final de um processo.

O que muitas APIs chamadas "REST" infelizmente fazem na realidade é tudo, menos isso. Você vê a troca principalmente de dados baseados em JSON, especificados em uma documentação externa específica da API que geralmente é difícil de integrar dinamicamente em tempo real. O formato em que uma solicitação precisa se parecer também é codificado na documentação externa, o que leva a muitas URIs de interpretação de implementação para retornar tipos predefinidosem vez de usar algum formato de representação comum negociado antecipadamente. Isso impede que os servidores sejam alterados, pois agora os clientes esperam receber um determinado formato de dados (observe o formato de não representação!) Para URIs predefinidos. Essa troca personalizada de formato de dados impede ainda que os clientes interajam com outras APIs, pois o "formato de dados" geralmente é uma maré para uma API específica. Conhecemos esse conceito no passado a partir de tecnologias RPC, como Corba, RMI ou SOAP, que condenamos como de alguma forma más, embora Peppol tenha se mudado para ele novamente substituindo o AS2 pelo AS4 como protocolo de transferência padrão recentemente.

Com relação à pergunta real, o envio de dados como arquivo csv não é diferente de usar application/x-www-form-urlencodedrepresentação ou algo semelhante. Jim Webber deixou claro que, afinal, o HTTP é apenas um protocolo de transporte cujo domínio de aplicativo é a transferência de documentos pela Web . Cliente e servidor devem ter pelo menos suporte, text/csvconforme definido na RFC 7111 . Esse arquivo CSV pode ser gerado como consequência do processamento de um tipo de mídia que define elementos de formulário, um elemento ou atributo de destino para enviar a solicitação e o método HTTP para executar o upload da configuração.

Existem alguns tipos de mídia compatíveis com formulários como HTML , HAL Forms , halform , ion ou Hydra . Atualmente, porém, não conheço um tipo de mídia que possa codificar automaticamente os dados de entrada text/csvdiretamente, portanto, pode ser necessário definir e registrar o registro de tipo de mídia da IANA. .

O upload e o download do conjunto completo de parâmetros não devem ser um problema, eu acho. Como mencionado anteriormente, o URI de destino não é relevante, pois um cliente apenas usará o URI para recuperar novo conteúdo para processar. A filtragem por data comercial também não deve ser difícil. Aqui o servidor deve, no entanto, o cliente com todas as possibilidades que o cliente simplesmente pode escolher. Nos últimos anos, o GraphQL e o RestQL evoluíram, introduzindo uma linguagem semelhante ao SQL que pode ser direcionada a um determinado endpoint para obter uma resposta filtrada. No entanto, no verdadeiro sentido REST, isso viola a idéia por trás do REST como: a) GraphQL, ou seja, usa apenas um único terminal que de alguma forma impede o uso ideal do armazenamento em cache eb) requer o conhecimento dos campos disponíveis com antecedência, o que pode levar à introdução de um acoplamento de clientes. para o modelo de dados base do recurso.

A ativação ou desativação de determinados parâmetros de configuração é simplesmente uma questão de acionar os controles hipermídia que fornecem essa disponibilidade. Nos formulários HTML, pode ser uma caixa de seleção simples ou uma seleção de várias linhas em uma lista ou esse tipo. Dependendo do formulário e do método que ele define, ele poderá enviar a configuração inteira via PUTou ser inteligente sobre as alterações feitas e realizar apenas uma atualização parcial via PATCH. O último requer basicamente um cálculo da representação de mudança para aquele atualizado e alimenta o servidor com as etapas necessárias para transformar a representação atual na desejada. De acordo com a especificação PATH, isso deve ser feito em uma transação para que todas ou nenhuma das etapas sejam aplicadas.

O HTTP permite e incentiva um servidor a validar uma solicitação recebida antecipadamente antes de aplicar as alterações. Para PUT, os estados de especificação:

Um servidor de origem DEVE verificar que a representação PUT é consistente com quaisquer restrições que o servidor tenha para o recurso de destino que não pode ou não será alterado pelo PUT. Isso é particularmente importante quando o servidor de origem usa informações de configuração interna relacionadas ao URI para definir os valores dos metadados de representação nas respostas GET. Quando uma representação PUT é inconsistente com o recurso de destino, o servidor de origem DEVE torná-los consistentes, transformando a representação ou alterando a configuração de recursos, ou responde com uma mensagem de erro apropriada contendo informações suficientes para explicar por que a representação é inadequada. Os códigos de status 409 (Conflito) ou 415 (Tipo de mídia não suportado) são sugeridos,

Por exemplo, se o recurso de destino estiver configurado para sempre ter um Tipo de Conteúdo de "text / html" e a representação sendo PUT possuir um Tipo de Conteúdo de "image / jpeg", o servidor de origem deverá executar um dos seguintes procedimentos:

uma. reconfigure o recurso de destino para refletir o novo tipo de mídia;

b. transforme a representação PUT em um formato consistente com o do recurso antes de salvá-lo como o novo estado do recurso; ou,

c. rejeite a solicitação com uma resposta 415 (Tipo de mídia não suportada) indicando que o recurso de destino está limitado a "text / html", talvez incluindo um link para um recurso diferente que seria um destino adequado para a nova representação.

O HTTP não define exatamente como um método PUT afeta o estado de um servidor de origem além do que pode ser expresso pela intenção da solicitação do agente do usuário e pela semântica da resposta do servidor de origem. ...

Para resumir esta postagem, você deve usar um tipo de mídia existente que permita ensinar um cliente sobre os parâmetros de entrada necessários ou suportados, o local de destino para o qual enviar a solicitação, a operação a ser usada e o tipo de mídia a solicitação deve ser formatada ou definir sua própria que você registra na IANA. O último pode ser necessário se você deseja converter a entrada emtext/csve faça o upload da representação CSV para o servidor. A validação deve ocorrer antes que as alterações sejam aplicadas ao recurso. O URI real não deve ser relevante para clientes, a não ser para determinar para onde enviar a solicitação e, como tal, pode ser escolhido livremente por você, o implementador do serviço. Ao seguir estas etapas, você obtém a liberdade de alterar o lado do servidor a qualquer momento e os clientes não quebram como consequência se oferecerem suporte aos tipos de mídia usados.

Roman Vottner
fonte
0

Edit: De fato, o URI teria impedido que as GETsolicitações permanecessem idempotentes.


Para a validação, no entanto, o uso de códigos de status HTTP para notificar a validade de uma solicitação (para criar um novo ou modificar um 'parâmetro' existente) se ajustaria a um modelo Restful.

Relate com um 400 Bad Requestcódigo de status se os dados enviados são / são inválidos e a solicitação deve ser alterada antes de ser reenviada ( códigos de status HTTP / 1.1 ).

Isso depende da validação no momento do envio, em vez de adiá-la como no seu caso de uso. As outras respostas têm soluções adequadas para esse cenário.

Derek Mortimer
fonte
O URI deve ser um identificador. O uso de um URL específico não deve ter efeitos colaterais. Imagine o que um proxy faria com isso.
24509 Breton
2
ou google, para esse assunto. Certa vez, li uma história sobre uma loja on-line que tinha todos os seus produtos excluídos pelo google por causa desse tipo de idiotice.
Breton
0

Em um ambiente REST, cada URL é um recurso exclusivo. Quais são os seus recursos? Uma calculadora financeira realmente não possui recursos óbvios. Você precisa se aprofundar no que está chamando de parâmetros e extrair os recursos. Por exemplo, um calendário de amortização para um empréstimo pode ser um recurso. O URL do calendário pode incluir data de início, prazo (em meses ou anos), período (quando os juros são compostos), taxa de juros e princípio inicial. Com todos esses valores, você tem um calendário de pagamentos específico:

http://example.com/amort_cal/2009-10-20/30yrsfixed/monthly/5.00/200000

Agora, não sei o que você está calculando, mas seu conceito de lista de parâmetros não parece RESTful. Como alguém disse, seus requisitos acima parecem mais XMLRPC. Se você está tentando fazer o REST, precisa de substantivos. Cálculos não são substantivos, são verbos que atuam sobre substantivos. Você precisa girá-lo para retirar os substantivos de seus cálculos.

jmucchiello
fonte
5
Eu acho um pouco tolo usar barras aqui, o que seria errado com amort_cal? Date = 20-10-2009 & type = 30yrsfixed & period = mensal & rate = 5.0 & initialamount = 200000? O REST não se importa, contanto que seja um recurso. A especificação do URI se importa. Como você imagina links relativos para trabalhar com um esquema como este?
Breton
Você traz um bom argumento, no entanto. Esses "parâmetros" ainda precisam ser armazenados no servidor? Se é apenas um cálculo único, por que não criar um espaço virtual, onde os parâmetros estão no URL. Contanto que você não esteja alterando o estado interno, tudo ficará bem.
Breton
1
E "parâmetros" não se aplicam a um "recurso". Um recurso é uma entidade única com um identificador exclusivo. Meu URL identifica um único recurso. Um URL parametrizado indica uma coleção de recursos que você seleciona usando os parâmetros.
jmucchiello
2
O REST não se baseia em "Recursos CRUDing". Colocar todos os seus parâmetros de consulta em segmentos de caminho não cria automaticamente uma interface RESTful, porque agora você acha que pode chamar cada recurso de permutação. Infelizmente, não existe um processo mágico que você possa aplicar para identificar quais devem ser os recursos em seu sistema. Requer um design cuidadoso, não uma fórmula mecânica.
Darrel Miller
2
Mais uma vez, a arquitetura REST não se importa com o conteúdo da URL. o URL deve ser opaco . Não importa se você usa barras, ponto-e-vírgula ou corações unicode como separadores. Leia isso e responda a isso - não ao que você imagina que eu esteja dizendo.
Breton