Eu preciso criar uma API de consulta RESTful, que retorna um conjunto de objetos com base em alguns filtros. O método HTTP usual para isso é GET. O único problema é que ele pode ter pelo menos uma dúzia de filtros e, se passarmos todos eles como parâmetros de consulta, a URL poderá ficar bastante longa (tempo suficiente para ser bloqueado por algum firewall).
Reduzir o número de parâmetros não é uma opção.
Uma alternativa em que eu poderia pensar é usar o método POST no URI e enviar os filtros como parte do corpo do POST. Isso é contra ser RESTfull (fazer uma chamada POST para consultar dados).
Alguém tem alguma sugestão de design melhor?
api
rest
http-parameters
missionE46
fonte
fonte
Respostas:
Lembre-se de que, com uma API REST, é tudo uma questão de seu ponto de vista.
Os dois conceitos principais em uma API REST são os terminais e os recursos (entidades). Em termos gerais, um ponto de extremidade retorna recursos via GET ou aceita recursos via POST e PUT e assim por diante (ou uma combinação dos itens acima).
É aceito que, com o POST, os dados que você envia podem ou não resultar na criação de um novo recurso e nos pontos de extremidade associados, que provavelmente não "viverão" sob o URL do POST. Em outras palavras, quando você POST envia os dados para algum lugar para manipulação. O terminal POST não é onde o recurso normalmente pode ser encontrado.
Citação da RFC 2616 (com partes irrelevantes omitidas e partes relevantes destacadas):
Nós nos acostumamos a pontos finais e recursos que representam 'coisas' ou 'dados', seja um usuário, uma mensagem, um livro - qualquer que seja o domínio do problema. No entanto, um terminal também pode expor um recurso diferente - por exemplo, resultados da pesquisa.
Considere o seguinte exemplo:
Este é um REST CRUD típico. No entanto, o que se adicionamos:
Não há nada de RESTful nesse terminal. Ele aceita dados (entidade) na forma do corpo da solicitação. Esses dados são os Critérios de pesquisa - um DTO como qualquer outro. Este terminal produz um recurso (entidade) em resposta à solicitação: Resultados da Pesquisa . O recurso de resultados da pesquisa é temporário, servido imediatamente ao cliente, sem redirecionamento e sem ser exposto a outros URLs canônicos.
Ainda é REST, exceto que as entidades não são livros - a entidade de solicitação é um critério de pesquisa de livros e a entidade de resposta é um resultado de pesquisa de livros.
fonte
BooksSearchCriteriaDTO
eBooksSearchResultsDTO
.POST
é usado para a parte C do CRUD. Eu iria com o simples velho 200, opcionalmente talvez com o 204 para resultados de pesquisa vazios.Muitas pessoas aceitaram a prática de que um GET com uma string de consulta muito longa ou muito complexa (por exemplo, as strings de consulta não manipulam dados aninhados facilmente) pode ser enviado como um POST, com os dados complexos / longos representados no corpo do pedido.
Procure a especificação para POST na especificação HTTP. É incrivelmente amplo. (Se você quiser navegar em um navio de guerra por uma brecha no REST ... use POST.)
Você perde alguns dos benefícios da semântica GET ... como tentativas automáticas porque GET é idempotente, mas se você pode conviver com isso, pode ser mais fácil aceitar o processamento de consultas realmente longas ou complicadas com o POST.
(lol digressão longa ... Descobri recentemente que, pelas especificações HTTP, o GET pode conter um corpo do documento. Há uma seção que diz, parafraseando: "Qualquer solicitação pode ter um corpo do documento, exceto os listados nesta seção" ... e a seção a que se refere não lista nenhuma. Pesquisei e encontrei um segmento em que os autores do HTTP estavam falando sobre isso, e era intencional, para que roteadores e outros não precisassem diferenciar entre mensagens diferentes. praticar muitas peças de infraestrutura soltam o corpo de um GET. Assim, você pode obter com filtros representados no corpo, como POST, mas você estaria lançando os dados.)
fonte
Em poucas palavras: faça um POST, mas substitua o método HTTP usando o cabeçalho X-HTTP-Method-Override .
Pedido real
POST / livros
Entidade
{"title": "Ipsum", "year": 2017}
Cabeçalhos
Substituição do método X-HTTP: GET
No lado do servidor, verifique se o cabeçalho X-HTTP-Method-Override existe e use seu valor como método para criar a rota para o terminal final no back-end. Além disso, considere o corpo da entidade como a string de consulta. Do ponto de vista de back-end, a solicitação se tornou apenas um GET simples.
Dessa forma, você mantém o design em harmonia com os princípios REST.
Edit: Eu sei que esta solução foi originalmente planejada para resolver o problema do verbo PATCH em alguns navegadores e servidores, mas também funciona para mim com o verbo GET no caso de uma URL muito longa, que é o problema descrito na pergunta.
fonte
X-
remoção existente e 1.5. ele não substitui as especificações existentes. ... AX-
IMO permanecerá aqui.Se você estiver desenvolvendo em Java e JAX-RS, recomendo usar o @QueryParam com o @GET
Eu tive a mesma pergunta quando precisei fazer uma lista.
Consultar exemplo:
Padrão de URI: “poc / test? Code = 1 & code = 2 & code = 3
O @QueryParam converterá o parâmetro de consulta "orderBy = age & orderBy = name" em java.util.List automaticamente.
fonte