Pagination dans une application REST web

il s'agit d'une reformulation plus générique de cette question (avec l'élimination des parties spécifiques des Rails)

Je ne suis pas sûr de savoir comment implémenter la pagination sur une ressource dans une application web reposante. En supposant que j'ai une ressource appelée products , que pensez-vous est la meilleure approche, et pourquoi:

1. Utilisant uniquement les chaînes de requête

par exemple. http://application/products?page=2&sort_by=date&sort_how=asc

le problème ici est que je ne peux pas utiliser la mise en cache pleine page et aussi L'URL n'est pas très propre et facile à se souvenir.

2. Utilisation des pages comme ressources et chaînes de requête pour le tri

par exemple. http://application/products/page/2?sort_by=date&sort_how=asc

dans ce cas, le problème qui se pose est que http://application/products/pages/1 n'est pas une ressource unique puisque l'utilisation de sort_by=price peut donner un résultat totalement différent et Je ne peux toujours pas utiliser la mise en cache de page.

3. Utilisation de pages comme ressources et d'un segment D'URL pour le tri

par exemple. http://application/products/by-date/page/2

personnellement, je ne vois aucun problème à utiliser cette méthode, mais quelqu'un m'a prévenu que ce n'est pas une bonne façon de faire (il n'a pas donné de raison, donc si vous savez pourquoi ce n'est pas recommandé, s'il vous plaît laissez-moi savoir)

Tout suggestions, opinions, critiques sont plus que bienvenus. Grâce.

314
demandé sur Community 2009-04-22 13:53:59
la source

12 ответов

je pense que le problème avec la version 3 est plus un" point de vue " problème - voyez-vous la page comme la ressource ou les produits sur la page.

si vous voyez la page comme la ressource, c'est une solution parfaite, puisque la requête pour la page 2 donnera toujours la page 2.

mais si vous voyez les produits sur la page comme la ressource vous avez le problème que les produits sur la page 2 pourraient changer (anciens produits supprimés, ou quoi que ce soit), dans ce cas, le URI n'est pas toujours de retour de la même ressource(s).

E. G. Un client stocke un lien vers la liste de produits page X, la prochaine fois que le lien est ouvert le produit en question pourrait ne plus être sur la page X.

60
répondu Fionn 2014-06-19 19:42:35
la source

je suis D'accord avec Fionn, mais je vais aller un peu plus loin et dire que pour moi la Page est pas une ressource, c'est une propriété de la requête. Cela me fait choisir l'option 1 chaîne de requête seulement. Il se sent juste à droite. J'aime vraiment la façon dont le API Twitter est structuré de manière réactive. Pas trop simple, pas trop compliqué, bien documenté. Pour le meilleur et pour le pire, c'est mon "go to" design quand je suis sur la défensive pour faire quelque chose d'une façon contre une autre.

102
répondu slf 2016-11-29 12:30:42
la source

HTTP a un grand en-tête de gamme qui est adapté à la pagination aussi. Vous pouvez envoyer

Range: pages=1

pour n'avoir que la première page. Qui peut vous forcer à repenser ce qu'est une page. Peut-être que le client veut une autre gamme d'articles. L'en-tête de gamme fonctionne également pour déclarer une commande:

Range: products-by-date=2009_03_27-

pour obtenir tous les produits plus récents que cette date ou

Range: products-by-date=0-2009_11_30

pour obtenir tous les produits plus anciens que cette date. '0' n'est probablement pas le meilleur solution, mais RFC semble vouloir quelque chose pour le démarrage de la portée. Il peut y avoir des parsers HTTP déployés qui ne parleraient pas units=-range_end.

si les en-têtes ne sont pas une option (acceptable), je pense que la première solution (tout dans la chaîne de requête) est une façon de traiter les pages. Mais s'il vous plaît, normalisez les chaînes de requête (trier (clé=valeur) les paires dans l'ordre alphabétique). Cela résout "?a=1 et b=x" et "?b=x et a=1" différenciation problème.

35
répondu temoto 2009-12-04 22:55:40
la source

L'Option 1 semble la meilleure, dans la mesure où votre application considère la pagination comme une technique pour produire une vue différente de la même ressource.

cela dit, le schéma D'URL est relativement insignifiant. Si vous concevez votre application comme étant "hypertext-driven (comme toutes les applications REST doivent être par définition), alors votre client ne construira pas d'URI seul. Au lieu de cela, votre application donnera les liens au client et le client les suivra.

un type de lien que votre client peut fournir est un lien de pagination.

l'effet secondaire agréable de tout cela est que même si vous changez d'avis sur la pagination URI structure et mettre en œuvre quelque chose de totalement différent la semaine prochaine, vos clients peuvent continuer à travailler sans aucune modification que ce soit.

24
répondu Rich Apodaca 2009-07-26 21:54:19
la source

j'ai toujours utilisé le style de l'option 1. La mise en cache n'a pas été un problème puisque les données changent fréquemment de toute façon dans mon cas. Si vous permettez à la taille de la page d'être configurable, alors encore une fois les données ne peuvent pas être mises en cache.

Je ne trouve pas l'url difficile à retenir ou impure. Pour moi, c'est une bonne utilisation des paramètres de requête. La ressource est clairement une liste de produits et les params de requête disent juste comment vous voulez que la liste affichée - triée et quelle page.

11
répondu John Snyders 2009-05-04 21:09:22
la source

étrange que personne n'ait fait remarquer que L'Option 3 a des paramètres dans un ordre précis. http//application/produits/Date/Descendant/Nom de/Montant/page/2 et http//application/produits/Nom de/Montant/Date/Descendant/page/2

pointent vers la même ressource, mais ont des urls complètement différentes.

pour moi L'Option 1 semble la plus acceptable, puisqu'elle sépare clairement "Ce que je veux" et "Comment je veux" (il a même un point d'interrogation entre eux lol). La mise en cache pleine page peut être implémentée en utilisant L'URL complète (toutes les options souffriront du même problème de toute façon).

avec L'approche parameter-in-URL le seul avantage est l'URL propre. Mais il faut trouver un moyen d'encoder les paramètres et de les décoder sans perte. Bien sûr, vous pouvez aller avec URLencode / decode, mais il fera urls laid à nouveau :)

8
répondu TEHEK 2010-03-17 02:26:07
la source

je préférerais utiliser les paramètres de requête offset et limit.

offset : pour l'index de la rubrique de la collection.

limite : pour le dénombrement des articles.

le client peut simplement continuer à mettre à jour l'offset comme suit

offset = offset + limit

pour la page suivante.

Le chemin est considéré comme l'identificateur de ressource. Et une page n'est pas ressource mais un sous-ensemble de la collection de ressources. Comme la pagination est généralement une requête GET, les paramètres de requête conviennent mieux à la pagination qu'aux en-têtes.

j'utilise metamug . Ils ont ce configurable. Pagination sur select query metamug

6
répondu Sorter 2017-05-23 14:47:05
la source

j'utilise actuellement un schéma similaire à celui-ci dans mon ASP.NET MVC apps:

p.ex. http://application/products/by-date/page/2

spécifiquement c'est : http://application/products/Date/Ascending/3

cependant, je ne suis pas vraiment content d'inclure des informations de paging et de tri dans le parcours de cette façon.

la liste des articles (produits dans ce cas) est mutable. c'est-à-dire que la prochaine fois que quelqu'un retourne à une url qui inclut des paramètres de pagination et de tri, le résultats qu'ils obtiennent peut-être changé. Ainsi, l'idée de http://application/products/Date/Ascending/3 comme une url unique qui pointe vers un ensemble défini et immuable de produits est perdue.

4
répondu Steve Willcock 2012-02-23 19:36:19
la source

a la recherche des meilleures pratiques je suis tombé sur ce site:

http://www.restapitutorial.com

dans la page de ressources il y a un lien pour télécharger a.pdf qui contient les meilleures pratiques complètes suggérées par l'auteur. Dans lequel il y a entre autres une section sur la pagination.

l'auteur suggère d'ajouter un support à la fois en utilisant un en-tête de gamme et en utilisant des paramètres de requête-chaîne.

demande

exemple D'en-tête HTTP:

Range: items=0-24

exemple de paramètres Query-string:

GET http://api.example.com/resources?offset=0&limit=25

offset est le numéro de début de l'article et limite est le nombre maximum d'articles à retourner.

réponse

La réponse doit inclure un En-tête Content-Range indiquant le nombre d'éléments retournés et le nombre total d'éléments qui n'ont pas encore été récupérés

exemples D'en-tête HTTP:

Content-Range: items 0-24/66

Content-Range: items 40-65/*

dans le .pdf il y a d'autres suggestions pour des cas plus spécifiques.

3
répondu Mario Arturo 2016-03-08 19:54:13
la source

j'ai tendance à être d'accord avec slf que "page" n'est pas vraiment une ressource. D'autre part, l'option 3 est plus propre, plus facile à lire, et peut être plus facilement deviné par l'utilisateur et même tapé si nécessaire. Je suis tiraillé entre les options 1 et 3, mais je ne vois aucune raison de ne pas utiliser l'option 3.

aussi, bien qu'ils semblent agréables, un inconvénient de l'utilisation de paramètres cachés, comme quelqu'un l'a mentionné, plutôt que des chaînes de requête ou des segments D'URL est que l'utilisateur ne peut pas ajouter de marque-page ou directement lien à une page particulière. Cela peut être ou ne pas être un problème selon l'application, mais juste quelque chose à savoir.

1
répondu insane.dreamer 2009-04-22 18:05:42
la source

j'ai déjà utilisé la solution 3 (j'écris beaucoup d'applications django). Et je ne pense pas qu'il y ait quelque chose de mal avec ça. Il est tout aussi générable que les deux autres (incase vous avez besoin de faire un peu de raclage de masse ou le genre) et il semble plus propre. De plus, vos utilisateurs peuvent deviner des urls (si c'est une application face au public), et les gens aiment être en mesure d'aller directement où ils le veulent, et la supposition d'url se sent autonomisant.

0
répondu Alex 2009-04-22 15:41:57
la source

j'utilise dans mes projets les urls suivantes:

http://application/products?page=2&sort=+field1-field2

ce qui signifie - "Donnez-moi la deuxième page ordonnée Ascendant Par field1 et ensuite Descendant Par field2". Ou si j'ai besoin de plus de flexibilité j'utilise:

http://application/products?skip=20&limit=20&sort=+field1-field2
0
répondu Eugene 2014-07-14 03:59:22
la source

Autres questions sur sorting rest pagination