Il s'agit d'une reformulation plus générique de cette question (avec l'élimination des parties spécifiques de Rails)
Je ne sais pas comment implémenter la pagination sur une ressource dans une application Web RESTful. En supposant que j'ai une ressource appelée products
, laquelle des options suivantes pensez-vous être la meilleure approche, et pourquoi:
1. Utiliser uniquement des 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 que l'URL n'est pas très propre et facile à retenir.
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 est que ce http://application/products/pages/1
n'est pas une ressource unique car l'utilisation 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. Utiliser des pages comme ressources et 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 averti que ce n'était pas une bonne façon de procéder (il n'a pas donné de raison, donc si vous savez pourquoi ce n'est pas recommandé, faites-le moi savoir)
Toutes suggestions, opinions, critiques sont les bienvenues. Merci.
la source
Réponses:
Je pense que le problème avec la version 3 est plus un problème de "point de vue" - 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 parfaitement adaptée, car 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 de la page 2 puissent changer (anciens produits supprimés, ou autre), dans ce cas, l'URI ne renvoie pas toujours les mêmes ressources.
Par exemple, un client stocke un lien vers la page de liste des produits X, la prochaine fois que le lien sera ouvert, le produit en question pourrait ne plus être sur la page X.
la source
Je suis d'accord avec Fionn, mais je vais aller plus loin et dire que pour moi la Page n'est pas une ressource, c'est une propriété de la demande. Cela me fait choisir la chaîne de requête de l'option 1 uniquement. Cela semble juste. J'aime vraiment la façon dont l' API Twitter est structurée de manière reposante. Pas trop simple, pas trop compliqué, bien documenté. Pour le meilleur ou pour le pire, c'est mon "go to" quand je suis sur le point de faire quelque chose d'une manière contre une autre.
la source
HTTP a un excellent en-tête Range qui convient également à la pagination. Vous pouvez envoyer
d'avoir seulement la première page. Cela peut vous obliger à repenser ce qu'est une page. Peut-être que le client veut une gamme d'articles différente. L'en-tête de plage fonctionne également pour déclarer une commande:
pour obtenir tous les produits plus récents que cette date ou
pour obtenir tous les produits antérieurs à cette date. '0' n'est probablement pas la meilleure solution, mais RFC semble vouloir quelque chose pour le début de la plage. Il peut y avoir des analyseurs HTTP déployés qui n'analyseraient pas units = -range_end.
Si les en-têtes ne sont pas une option (acceptable), je pense que la première solution (tous dans la chaîne de requête) est un moyen de traiter les pages. Mais veuillez normaliser les chaînes de requête (trier (clé = valeur) paires dans l'ordre alphabétique). Cela résout le problème de différenciation "? A = 1 & b = x" et "? B = x & a = 1".
la source
range-unit = bytes-unit | other-range-unit
Peut-être que vous faites référence àThe only range unit defined by HTTP/1.1 is "bytes". HTTP/1.1 implementations MAY ignore ranges specified using other units.
ce n'est pas la même chose que votre déclaration.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 de manière à être hypertexte (comme toutes les applications REST doivent l'être par définition), 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 structure de l'URI de pagination et implémentez quelque chose de totalement différent la semaine prochaine, vos clients peuvent continuer à travailler sans aucune modification.
la source
J'ai toujours utilisé le style de l'option 1. La mise en cache n'a pas été un problème car les données changent fréquemment de toute façon dans mon cas. Si vous autorisez la taille de la page à être configurable, 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 paramètres de requête indiquent simplement comment vous voulez que la liste soit affichée - triée et quelle page.
la source
Étrange que personne n'ait souligné que l'option 3 a des paramètres dans un ordre spécifique. http // application / produits / Date / Décroissant / Nom / Croissant / page / 2 et http // application / produits / Nom / Croissant / Date / Décroissant / page / 2
pointent vers la même ressource, mais ont des URL complètement différentes.
Pour moi, l'option 1 semble la plus acceptable, car elle sépare clairement "ce que je veux" et "comment je veux" (elle a même un point d'interrogation entre eux lol). La mise en cache pleine page peut être implémentée à l'aide de l'URL complète (toutes les options subiront le même problème de toute façon).
Avec l'approche des paramètres dans l'URL, le seul avantage est une URL propre. Bien que vous deviez 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 cela rendra les URL laides à nouveau :)
la source
Je préfère utiliser les paramètres de requête offset et limit.
offset : pour l'index de l'élément dans la collection.
limite : pour le nombre d'articles.
Le client peut simplement continuer à mettre à jour l'offset comme suit
pour la page suivante.
Le chemin est considéré comme l'identifiant de la ressource. Et une page n'est pas une ressource mais un sous-ensemble de la collection de ressources. Étant donné que la pagination est généralement une demande GET, les paramètres de requête conviennent mieux à la pagination qu'aux en-têtes.
Référence: https://metamug.com/article/rest-api-developers-dilemma.html#Requesting-the-next-page
la source
À la recherche des meilleures pratiques, je suis tombé sur ce site:
http://www.restapitutorial.com
Dans la page des ressources, il y a un lien pour télécharger un .pdf qui contient les meilleures pratiques REST complètes suggérées par l'auteur. Dans lequel, entre autres, il y a une section sur la pagination.
L'auteur suggère d'ajouter un support à la fois en utilisant un en-tête Range et en utilisant des paramètres de chaîne de requête.
Demande
Exemple d'en-tête HTTP:
Exemple de paramètres de chaîne de requête:
Où offset est le numéro d'article de début et limit 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 restent à récupérer.
Exemples d'en-tête HTTP:
Dans le .pdf il y a quelques autres suggestions pour des cas plus spécifiques.
la source
J'utilise actuellement un schéma similaire à celui-ci dans mes applications ASP.NET MVC:
par exemple
http://application/products/by-date/page/2
spécifiquement c'est:
http://application/products/Date/Ascending/3
Cependant, je ne suis pas vraiment heureux d'inclure des informations de pagination et de tri dans l'itinéraire de cette manière.
La liste des articles (produits dans ce cas) est modifiable. c'est-à-dire que la prochaine fois que quelqu'un reviendra à une URL qui inclut des paramètres de pagination et de tri, les résultats qu'ils obtiendront auront peut-être changé. L'idée d'
http://application/products/Date/Ascending/3
une URL unique pointant vers un ensemble de produits défini et immuable est donc perdue.la source
J'ai tendance à être d'accord avec slf que la "page" n'est pas vraiment une ressource. D'un autre côté, l'option 3 est plus propre, plus facile à lire et peut être plus facilement devinée par l'utilisateur et même tapée si nécessaire. Je suis déchiré entre les options 1 et 3, mais je ne vois aucune raison de ne pas utiliser l'option 3.
En outre, bien qu'ils semblent agréables, l'un des inconvénients de l'utilisation de paramètres cachés, comme quelqu'un l'a mentionné, plutôt que de chaînes de requête ou de segments d'URL, est que l'utilisateur ne peut pas créer de signet ou créer un lien direct vers une page particulière. Cela peut ou non être un problème selon l'application, mais juste quelque chose à savoir.
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 à cela. Il est tout aussi générable que les deux autres (au cas où vous devriez faire un grattage de masse ou similaire) et il semble plus propre. De plus, vos utilisateurs peuvent deviner les URL (s'il s'agit d'une application accessible au public), et les gens aiment pouvoir aller directement où ils veulent, et la devinette des URL est valorisante.
la source
J'utilise dans mes projets les URL suivantes:
ce qui signifie - "donnez-moi la page la deuxième page ordonnée ascendante par champ1 puis décroissante par champ2". Ou si j'ai besoin de plus de flexibilité, j'utilise:
la source
J'utilise dans les modèles suivants pour obtenir l'enregistrement de la page suivante. http: // application / produits? lastRecordKey =? & pageSize = 20 & sort = ASC
RecordKey est la colonne d'une table qui contient une valeur séquentielle dans DB. Il est utilisé pour extraire une seule page à la fois de la base de données. pageSize est utilisé pour déterminer le nombre d'enregistrements à récupérer. sort est utilisé pour trier l'enregistrement dans l'ordre croissant ou décroissant.
la source