Esta é uma reformulação mais genérica dessa questão (com a eliminação das partes específicas do Rails)
Não sei como implementar a paginação em um recurso em um aplicativo Web RESTful. Supondo que eu tenha um recurso chamado products
, qual das seguintes opções você acha que é a melhor abordagem e por quê:
1. Usando apenas cadeias de consulta
por exemplo. http://application/products?page=2&sort_by=date&sort_how=asc
O problema aqui é que não consigo usar o cache de página inteira e também o URL não é muito limpo e fácil de lembrar.
2. Usando páginas como recursos e cadeias de consulta para classificação
por exemplo. http://application/products/page/2?sort_by=date&sort_how=asc
Nesse caso, o problema que se vê é que http://application/products/pages/1
não é um recurso exclusivo, pois o uso sort_by=price
pode gerar um resultado totalmente diferente e ainda não consigo usar o cache da página.
3. Usando páginas como recursos e um segmento de URL para classificação
por exemplo. http://application/products/by-date/page/2
Pessoalmente, não vejo problema em usar esse método, mas alguém me avisou que esse não é um bom caminho a seguir (ele não deu um motivo, por isso, se você souber por que não é recomendado, entre em contato)
Quaisquer sugestões, opiniões e críticas são bem-vindas. Obrigado.
fonte
Respostas:
Eu acho que o problema com a versão 3 é mais um problema do "ponto de vista" - você vê a página como recurso ou produtos na página.
Se você vir a página como o recurso, é uma solução perfeita, pois a consulta da página 2 sempre produzirá a página 2.
Mas se você vê os produtos na página como o recurso, tem o problema de os produtos na página 2 poderem ser alterados (produtos antigos excluídos ou o que for), nesse caso, o URI nem sempre retorna os mesmos recursos.
Por exemplo, um cliente armazena um link para a página da lista de produtos X. Na próxima vez em que o link for aberto, o produto em questão poderá não estar mais na página X.
fonte
Eu concordo com Fionn, mas vou dar um passo adiante e dizer que para mim a página não é um recurso, é uma propriedade da solicitação. Isso me faz escolher apenas a opção 1 da string de consulta. Parece certo. Eu realmente gosto de como a API do Twitter é estruturada de maneira tranqüila. Não é muito simples, nem muito complicado, bem documentado. Para o bem ou para o mal, é o meu design "ir para" quando estou em cima do muro fazendo algo de um jeito contra o outro.
fonte
O HTTP possui um ótimo cabeçalho Range, que também é adequado para paginação. Você pode enviar
ter apenas a primeira página. Isso pode forçá-lo a repensar o que é uma página. Talvez o cliente queira uma gama diferente de itens. O cabeçalho do intervalo também funciona para declarar um pedido:
para obter todos os produtos mais novos que essa data ou
para obter todos os produtos mais antigos que essa data. '0' provavelmente não é a melhor solução, mas a RFC parece querer algo para o início do intervalo. Pode haver analisadores HTTP implantados que não analisariam unidades = -range_end.
Se os cabeçalhos não forem uma opção (aceitável), considero que a primeira solução (tudo na string de consulta) é uma maneira de lidar com as páginas. Mas, por favor, normalize as cadeias de consulta (classifique (chave = valor) pares em ordem alfabética). Isso resolve o problema de diferenciação "? A = 1 & b = x" e "? B = x & a = 1".
fonte
range-unit = bytes-unit | other-range-unit
Talvez você esteja se referindo aThe only range unit defined by HTTP/1.1 is "bytes". HTTP/1.1 implementations MAY ignore ranges specified using other units.
Isso não é o mesmo que sua declaração.A opção 1 parece a melhor, na medida em que seu aplicativo vê a paginação como uma técnica para produzir uma exibição diferente do mesmo recurso.
Dito isto, o esquema de URL é relativamente insignificante. Se você estiver projetando seu aplicativo para ser direcionado por hipertexto (como todos os aplicativos REST devem ser por definição), seu cliente não estará construindo nenhum URI sozinho. Em vez disso, seu aplicativo fornecerá os links para o cliente e o cliente os seguirá.
Um tipo de link que seu cliente pode fornecer é um link de paginação.
O efeito colateral agradável de tudo isso é que, mesmo que você mude de idéia sobre a estrutura de URI de paginação e implemente algo totalmente diferente na próxima semana, seus clientes poderão continuar trabalhando sem nenhuma modificação.
fonte
Eu sempre usei o estilo da opção 1. O cache não tem sido uma preocupação, pois os dados mudam frequentemente de qualquer maneira no meu caso. Se você permitir que o tamanho da página seja configurável, os dados não poderão ser armazenados em cache novamente.
Não acho o URL difícil de lembrar ou imundo. Para mim, este é um bom uso de parâmetros de consulta. O recurso é claramente uma lista de produtos e os parâmetros de consulta estão apenas dizendo como você deseja que a lista seja exibida - classificada e qual página.
fonte
Estranho que ninguém tenha apontado que a opção 3 possui parâmetros em uma ordem específica. http // aplicativo / produtos / Data / Decrescente / Nome / Crescente / página / 2 e http // aplicativo / produtos / Nome / Crescente / Data / Decrescente / página / 2
estão apontando para o mesmo recurso, mas têm URLs completamente diferentes.
Para mim, a opção 1 parece a mais aceitável, uma vez que separa claramente "o que eu quero" e "como eu quero" (ele ainda tem um ponto de interrogação entre eles, risos). O cache de página inteira pode ser implementado usando URL completo (todas as opções sofrerão o mesmo problema).
Com a abordagem Parameters-in-URL, o único benefício é o URL limpo. Embora você precise criar uma maneira de codificar parâmetros e decodificá-los sem perdas. Claro que você pode usar o URLencode / decodificar, mas isso tornará os URLs feios novamente :)
fonte
Eu preferiria usar parâmetros de consulta offset e limit.
offset : para o índice do item na coleção.
limite : para contagem de itens.
O cliente pode simplesmente continuar atualizando o deslocamento da seguinte maneira
para a próxima página.
O caminho é considerado o identificador de recurso. E uma página não é um recurso, mas um subconjunto da coleção de recursos. Como a paginação geralmente é uma solicitação GET, os parâmetros de consulta são mais adequados para paginação do que para cabeçalhos.
Referência: https://metamug.com/article/rest-api-developers-dilemma.html#Requesting-the-next-page
fonte
Procurando as melhores práticas, deparei-me com este site:
http://www.restapitutorial.com
Na página de recursos, há um link para baixar um arquivo .pdf que contém as melhores práticas completas de REST sugeridas pelo autor. Em que, entre outras coisas, há uma seção sobre paginação.
O autor sugere adicionar suporte a ambos, usando um cabeçalho Range e usando parâmetros de string de consulta.
Solicitação
Exemplo de cabeçalho HTTP:
Exemplo de parâmetros de cadeia de consulta:
Onde deslocamento é o número do item inicial e limite é o número máximo de itens a serem retornados.
Resposta
A resposta deve incluir um cabeçalho Content-Range indicando quantos itens estão sendo retornados e quantos itens totais existem ainda para serem recuperados
Exemplos de cabeçalho HTTP:
No arquivo .pdf, existem outras sugestões para casos mais específicos.
fonte
Atualmente, estou usando um esquema semelhante a este em meus aplicativos ASP.NET MVC:
por exemplo
http://application/products/by-date/page/2
especificamente é:
http://application/products/Date/Ascending/3
No entanto, não estou muito feliz em incluir informações de paginação e classificação na rota dessa maneira.
A lista de itens (produtos neste caso) é mutável. ou seja, na próxima vez que alguém retornar a um URL que inclua parâmetros de paginação e classificação, os resultados obtidos poderão ter sido alterados. Portanto, a idéia de
http://application/products/Date/Ascending/3
um URL exclusivo que aponta para um conjunto definido e imutável de produtos é perdida.fonte
Costumo concordar com o slf que "página" não é realmente um recurso. Por outro lado, a opção 3 é mais limpa, fácil de ler e pode ser mais facilmente adivinhada pelo usuário e digitada, se necessário. Estou dividido entre as opções 1 e 3, mas não vejo motivo para não usar a opção 3.
Além disso, embora eles tenham uma boa aparência, uma desvantagem do uso de parâmetros ocultos, como alguém mencionado, em vez de cadeias de consulta ou segmentos de URL, é que o usuário não pode marcar ou vincular diretamente a uma página específica. Isso pode ou não ser um problema, dependendo do aplicativo, mas apenas algo para estar ciente.
fonte
Eu usei a solução 3 antes (eu escrevo muitos aplicativos de django). E eu não acho que haja algo errado com isso. É tão gerador quanto os outros dois (caso você precise fazer uma raspagem em massa ou algo semelhante) e parece mais limpo. Além disso, seus usuários podem adivinhar URLs (se for um aplicativo voltado para o público), e as pessoas gostam de poder ir diretamente para onde desejam, e a adivinhação de URLs é poderosa.
fonte
Eu uso em meus projetos os seguintes URLs:
o que significa - "dê-me página a segunda página ordenada ascendente pelo campo1 e depois descendente pelo campo2". Ou, se precisar de mais flexibilidade, uso:
fonte
Uso nos seguintes padrões para obter o próximo registro da página. http: // application / products? lastRecordKey =? & pageSize = 20 & sort = ASC
RecordKey é a coluna de uma tabela que contém valor seqüencial no banco de dados. Isso é usado para buscar apenas dados de uma página por vez no DB. pageSize é usado para determinar quantos registros buscar. sort é usado para classificar o registro em ordem crescente ou decrescente.
fonte