Ultimamente, tenho pesquisado extensivamente essa e outras perguntas relacionadas à paginação REST e achei construtivo adicionar algumas das minhas descobertas aqui. Estou expandindo um pouco a questão para incluir pensamentos sobre paginação, bem como a contagem, pois eles estão intimamente relacionados.
Cabeçalhos
Os metadados de paginação são incluídos na resposta na forma de cabeçalhos de resposta. O grande benefício dessa abordagem é que a carga útil da resposta é exatamente o que o solicitante de dados real estava solicitando. Facilitando o processamento da resposta para clientes que não estão interessados nas informações de paginação.
Existem vários cabeçalhos (padrão e personalizados) usados em caráter selvagem para retornar informações relacionadas à paginação, incluindo a contagem total.
Contagem X total
X-Total-Count: 234
Isso é usado em algumas APIs que encontrei na natureza. Existem também pacotes NPM para adicionar suporte a este cabeçalho, por exemplo, Loopback. Alguns artigos recomendam a configuração desse cabeçalho também.
Geralmente é usado em combinação com o Link
cabeçalho, que é uma solução muito boa para paginação, mas não possui as informações totais de contagem.
Ligação
Link: </TheBook/chapter2>;
rel="previous"; title*=UTF-8'de'letztes%20Kapitel,
</TheBook/chapter4>;
rel="next"; title*=UTF-8'de'n%c3%a4chstes%20Kapitel
Sinto-me, de ler muito sobre este assunto, que o consenso geral é usar o Link
cabeçalho para fornecer paginação links para clientes usando rel=next
, rel=previous
etc. O problema com isto é que ela não tem a informação de quantos registros totais existem, o que é por que muitas APIs combinam isso com o X-Total-Count
cabeçalho.
Como alternativa, algumas APIs e, por exemplo, o padrão JsonApi , usam o Link
formato, mas adicionam as informações em um envelope de resposta em vez de em um cabeçalho. Isso simplifica o acesso aos metadados (e cria um local para adicionar as informações totais da contagem) às custas do aumento da complexidade do acesso aos próprios dados reais (adicionando um envelope).
Intervalo de conteúdo
Content-Range: items 0-49/234
Promovido por um artigo de blog chamado Range header, eu escolho você (para paginação)! . O autor defende fortemente o uso dos cabeçalhos Range
e Content-Range
para paginação. Quando lemos atentamente a RFC nesses cabeçalhos, descobrimos que estender seu significado além dos intervalos de bytes foi realmente antecipado pela RFC e é explicitamente permitido. Quando usado no contexto de em items
vez de bytes
, o cabeçalho Range realmente nos permite solicitar um certo intervalo de itens e indicar a qual intervalo do resultado total os itens de resposta se referem. Esse cabeçalho também oferece uma ótima maneira de mostrar a contagem total. E é um verdadeiro padrão que mapeia principalmente a paginação individual. Também é usado na natureza .
Envelope
Muitas APIs, incluindo a do nosso site de perguntas e respostas favorito, usam um envelope , um invólucro em torno dos dados que são usados para adicionar meta informações sobre os dados. Além disso, os padrões OData e JsonApi usam um envelope de resposta.
A grande desvantagem disso (imho) é que o processamento dos dados de resposta se torna mais complexo, pois os dados reais precisam ser encontrados em algum lugar do envelope. Além disso, existem muitos formatos diferentes para esse envelope e você precisa usar o correto. É revelador que os envelopes de resposta do OData e JsonApi são totalmente diferentes, com o OData misturando metadados em vários pontos da resposta.
Ponto final separado
Eu acho que isso foi abordado o suficiente nas outras respostas. Não investiguei muito isso, porque concordo com os comentários de que isso é confuso, pois agora você tem vários tipos de pontos de extremidade. Eu acho que é melhor se cada endpoint representar um (conjunto de) recursos.
Pensamentos adicionais
Não precisamos apenas comunicar as meta informações de paginação relacionadas à resposta, mas também permitir que o cliente solicite páginas / intervalos específicos. É interessante observar também esse aspecto para obter uma solução coerente. Aqui também podemos usar cabeçalhos (o Range
cabeçalho parece muito adequado) ou outros mecanismos, como parâmetros de consulta. Algumas pessoas defendem o tratamento de páginas de resultados como recursos separados, o que pode fazer sentido em alguns casos de uso (por exemplo /books/231/pages/52
, acabei selecionando uma variedade de parâmetros de solicitação usados com frequência, como pagesize
, page[size]
e limit
etc, além de oferecer suporte ao Range
cabeçalho (e como parâmetro de solicitação também).