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 Linkcabeç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 Linkcabeçalho para fornecer paginação links para clientes usando rel=next, rel=previousetc. 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-Countcabeçalho.
Como alternativa, algumas APIs e, por exemplo, o padrão JsonApi , usam o Linkformato, 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 Rangee Content-Rangepara 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 itemsvez 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 Rangecabeç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 limitetc, além de oferecer suporte ao Rangecabeçalho (e como parâmetro de solicitação também).