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:
- Carregar novos parâmetros
- Obtenha os parâmetros mais recentes
- Obter parâmetros para uma determinada data comercial
- Ativar um conjunto de parâmetros
- 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:
- POST em que você inclui o arquivo de parâmetro na solicitação de postagem
- GET do primeiro URL
- 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
??
rest
restful-url
Marcus Leon
fonte
fonte
Respostas:
Talvez algo como:
fonte
POST
está 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.POST
vsPUT
não é exatamente comoinsert
vsupdate
.PUT
atualiza o recurso correspondente ao caminho especificado ou cria um novo recurso correspondente ao caminho especificado.POST
cria um novo recurso em algum lugar. Por exemplo,PUT /blog/posts/3/comments/5
atualizará o comentário apropriado, enquantoPOST /blog/posts/3/comments
criará um novocomment
recurso (e deve retornar o caminho para o novo recurso na resposta).PUT
é idempotente enquantoPOST
não é. Normalmente, você deve colocar o máximo de restrições sobre o que fornecer como resultado possível. Ficar comPUT
fornece mais informações ao cliente do serviço.Princípios gerais para um bom design de URI:
/resource
ou/resource/
; crie 301 redirecionamentos daquele que você não usa(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:
Princípios gerais de design de serviços da web com HTTP:
201 Created
depois de criar um recurso; O recurso deve existir no momento em que a resposta é enviada202 Accepted
depois de executar uma operação com sucesso ou criar um recurso de forma assíncrona400 Bad Request
quando 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 capturadas401 Unauthorized
quando alguém acessa sua API sem fornecer umAuthorization
cabeçalho necessário ou quando as credenciais dentro daAuthorization
são inválidas; não use esse código de resposta se não estiver esperando credenciais por meio de umAuthorization
cabeçalho.403 Forbidden
quando alguém acessa sua API de uma maneira que possa ser maliciosa ou se não está autorizada405 Method Not Allowed
quando alguém usa POST quando deveria ter usado PUT, etc413 Request Entity Too Large
quando alguém tenta enviar para você um arquivo inaceitavelmente grande418 I'm a teapot
ao tentar preparar café com um bule de cháETag
cabeçalhos são bons quando você pode reduzir facilmente um recurso a um valor de hashLast-Modified
deve indicar a você que manter um registro de data e hora de quando os recursos são atualizados é uma boa ideiaCache-Control
eExpires
devem receber valores sensatosIf-None-Modified
,If-Modified-Since
)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.fonte
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 .
fonte
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:
Mas, novamente, essa coisa de ativação é RPC, não REST.
fonte
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,
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:
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.
fonte
Eu sugeriria o seguinte recurso e métodos Meta.
Ative os parâmetros e / ou valide-os:
Verifique se os parâmetros estão ativos e válidos:
fonte
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 de
application/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: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-urlencoded
formato de representação enviado para o local de destino mencionado por meio do método de solicitação HTTP especificado,POST
neste caso. Se entrarmos1
nofirstNumber
campo de entrada e2
nosecondNumber
campo de entrada, o navegador gerará uma representaçãofirstNumber=1&secondNumber=2
e 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:
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
preload
links 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-urlencoded
representaçã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/csv
conforme 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/csv
diretamente, 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
PUT
ou ser inteligente sobre as alterações feitas e realizar apenas uma atualização parcial viaPATCH
. 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:
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 em
text/csv
e 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.fonte
Edit: De fato, o URI teria impedido que as
GET
solicitaçõ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 Request
có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.
fonte
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:
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.
fonte