J'ai récemment fait des recherches approfondies sur cette question et sur d'autres questions liées à la pagination REST et j'ai pensé qu'il était constructif d'ajouter certaines de mes conclusions ici. J'élargis un peu la question pour inclure des réflexions sur la pagination ainsi que sur le décompte car elles sont intimement liées.
En-têtes
Les métadonnées de pagination sont incluses dans la réponse sous la forme d'en-têtes de réponse. Le grand avantage de cette approche est que la charge utile de la réponse elle-même n'est que la demande de données réelle. Faciliter le traitement de la réponse pour les clients qui ne sont pas intéressés par les informations de pagination.
Il existe de nombreux en-têtes (standard et personnalisés) utilisés à l'état sauvage pour renvoyer des informations relatives à la pagination, y compris le nombre total.
Nombre total X
X-Total-Count: 234
Ceci est utilisé dans certaines API que j'ai trouvées dans la nature. Il existe également des packages NPM pour ajouter la prise en charge de cet en-tête, par exemple Loopback. Certains articles recommandent également de définir cet en-tête.
Il est souvent utilisé en combinaison avec l'en- Link
tête, qui est une très bonne solution pour la pagination, mais ne dispose pas des informations de comptage total.
Lien
Link: </TheBook/chapter2>;
rel="previous"; title*=UTF-8'de'letztes%20Kapitel,
</TheBook/chapter4>;
rel="next"; title*=UTF-8'de'n%c3%a4chstes%20Kapitel
J'ai le sentiment, après avoir lu beaucoup sur ce sujet, que le consensus général est d'utiliser l'en- Link
tête pour fournir des liens de pagination aux clients utilisant rel=next
, rel=previous
etc. Le problème avec cela est qu'il manque d'informations sur le nombre total d'enregistrements, ce qui pourquoi de nombreuses API combinent cela avec l'en- X-Total-Count
tête.
Alternativement, certaines API et par exemple la norme JsonApi , utilisent le Link
format, mais ajoutent les informations dans une enveloppe de réponse au lieu de dans un en-tête. Cela simplifie l'accès aux métadonnées (et crée un emplacement pour ajouter les informations de comptage total) au détriment de la complexité croissante de l'accès aux données réelles elles-mêmes (en ajoutant une enveloppe).
Gamme de contenu
Content-Range: items 0-49/234
Promu par un article de blog nommé Range header, je vous choisis (pour la pagination)! . L'auteur plaide fermement en faveur de l'utilisation des en Range
- Content-Range
têtes et pour la pagination. Lorsque nous lisons attentivement la RFC sur ces en-têtes, nous constatons que l'extension de leur signification au-delà des plages d'octets était en fait anticipée par la RFC et est explicitement autorisée. Lorsqu'il est utilisé dans le contexte de items
plutôt que de bytes
, l'en-tête Range nous donne en fait un moyen de demander une certaine plage d'éléments et d'indiquer à quelle plage du résultat total les éléments de réponse se rapportent. Cet en-tête offre également un excellent moyen d'afficher le nombre total. Et c'est un vrai standard qui mappe principalement un à un à la pagination. Il est également utilisé dans la nature .
Enveloppe
De nombreuses API, y compris celle de notre site Web de questions-réponses préféré, utilisent une enveloppe , un wrapper autour des données qui est utilisé pour ajouter des méta-informations sur les données. De plus, les normes OData et JsonApi utilisent toutes deux une enveloppe de réponse.
Le gros inconvénient de cela (à mon humble avis) est que le traitement des données de réponse devient plus complexe car les données réelles doivent être trouvées quelque part dans l'enveloppe. Il existe également de nombreux formats différents pour cette enveloppe et vous devez utiliser le bon. Il est révélateur que les enveloppes de réponse d'OData et de JsonApi sont extrêmement différentes, OData se mélangeant dans les métadonnées à plusieurs points de la réponse.
Point de terminaison séparé
Je pense que cela a été suffisamment couvert dans les autres réponses. Je n'ai pas beaucoup enquêté car je suis d'accord avec les commentaires selon lesquels cela prête à confusion car vous avez maintenant plusieurs types de points de terminaison. Je pense que c'est plus agréable si chaque point de terminaison représente une (collection de) ressource (s).
Réflexions supplémentaires
Nous devons non seulement communiquer les méta-informations de pagination liées à la réponse, mais aussi permettre au client de demander des pages / plages spécifiques. Il est intéressant de se pencher également sur cet aspect pour aboutir à une solution cohérente. Ici aussi, nous pouvons utiliser des en-têtes (l'en- Range
tête semble très approprié), ou d'autres mécanismes tels que les paramètres de requête. Certaines personnes préconisent le traitement des pages de résultats comme des ressources distinctes, ce qui peut donner un sens dans certains cas d'utilisation (par exemple /books/231/pages/52
. J'ai fini par sélectionner une plage sauvage de paramètres de demande fréquemment utilisés tels que pagesize
, page[size]
et limit
etc , en plus de soutenir l' en- Range
tête (et comme paramètre de requête ainsi que).