Je souhaite rendre mon API RESTful très prévisible. Quelle est la meilleure pratique pour décider quand effectuer une segmentation de données à l'aide de l'URI plutôt qu'en utilisant des paramètres de requête.
Il est logique pour moi que les paramètres système prenant en charge la pagination, le tri et le regroupement soient après le '?' Mais qu'en est-il des champs tels que "statut" et "région" ou d'autres attributs qui segmentent votre collection? Si ceux-ci doivent également être des paramètres de requête, quelle est la règle de base pour savoir quand utiliser les paramètres de chemin?
La meilleure pratique pour la conception de l'API RESTful est que les paramètres de chemin soient utilisés pour identifier une ressource ou des ressources spécifiques, alors que les paramètres de requête sont utilisés pour trier/filtrer ces ressources.
Voici un exemple. Supposons que vous implémentez des points de terminaison d'API RESTful pour une entité appelée Car. Vous structureriez vos points d'extrémité de la manière suivante:
OBTENIR /cars
GET /cars/:id
POST /cars
PUT /cars/:id
SUPPRIMER /cars/:id
De cette façon, vous utilisez uniquement les paramètres de chemin lorsque vous spécifiez la ressource à extraire, sans que cela ne trie/filtre les ressources.
Supposons maintenant que vous souhaitiez ajouter la possibilité de filtrer les voitures par couleur dans vos demandes GET. Comme la couleur n'est pas une ressource (c'est une propriété d'une ressource), vous pouvez ajouter un paramètre de requête qui le fait. Vous ajouteriez ce paramètre de requête à votre requête GET /cars
comme ceci:
OBTENIR /cars?color=blue
Ce point final serait mis en œuvre de sorte que seules les voitures bleues soient renvoyées.
En ce qui concerne la syntaxe, vos noms d'URL doivent être en minuscules. Si vous avez un nom d'entité qui est généralement deux mots en anglais, vous utiliserez un trait d'union pour séparer les mots, et non un cas de chameau.
Ex. /two-words
La façon fondamentale de penser à ce sujet est la suivante:
Un URI est un identifiant de ressource qui identifie de manière unique une instance spécifique d'un type de ressource. Comme tout le reste de la vie, chaque objet (qui est une instance d'un type) possède un ensemble d'attributs invariants dans le temps ou temporels.
Dans l'exemple ci-dessus, une voiture est un objet très concret qui possède des attributs tels que la marque, le modèle et le NIV - qui ne changent jamais, et la couleur, la suspension, etc. qui peuvent changer avec le temps. Donc, si nous encodons l'URI avec des attributs qui peuvent changer dans le temps (temporel), nous pouvons nous retrouver avec plusieurs URI pour le même objet:
GET /cars/honda/civic/coupe/{vin}/{color=red}
Et des années plus tard, si la couleur de cette même voiture passe au noir:
GET /cars/honda/civic/coupe/{vin}/{color=black}
Notez que l'instance de voiture elle-même (l'objet) n'a pas changé - c'est simplement la couleur qui a changé. Avoir plusieurs URI pointant vers la même instance d'objet vous obligera à créer plusieurs gestionnaires d'URI - ceci n'est pas une conception efficace, et n'est bien sûr pas intuitive.
Par conséquent, l'URI ne doit contenir que des parties qui ne changeront jamais et qui continueront d'identifier de manière unique cette ressource tout au long de sa vie. Tout ce qui peut changer doit être réservé aux paramètres de requête, en tant que tel:
GET /cars/honda/civic/coupe/{vin}?color={black}
En bout de ligne - pensez polymorphisme.
Dans une API REST, vous ne devriez pas être trop préoccupé par les URI prévisibles. La suggestion même de la prévisibilité URI fait allusion à une incompréhension de l'architecture RESTful. Cela suppose qu'un client doit construire lui-même les adresses URI, ce qu'il ne devrait vraiment pas avoir à le faire.
Cependant, je suppose que vous ne créez pas une vraie API REST, mais une API inspirée de REST (telle que celle de Google Drive). Dans ces cas, la règle de base est 'path params = identification de la ressource' et 'query params = resource triage'. La question est donc la suivante: pouvez-vous identifier de manière unique votre ressource SANS statut/région? Si oui, alors peut-être que c'est un paramètre de requête. Si non, alors c'est un chemin param.
HTH.
Une fois, j'ai conçu une API dont la ressource principale était people
. Habituellement, les utilisateurs demandaient filtré people
donc, pour empêcher les utilisateurs d'appeler à chaque fois quelque chose comme /people?settlement=urban
, j'ai implémenté /people/urban
, ce qui m'a ensuite permis d'ajouter facilement /people/rural
. Cela permet également d’accéder à la liste complète /people
si elle peut être utilisée ultérieurement. En bref, mon raisonnement était d’ajouter un chemin aux sous-ensembles communs
De ici :
Alias pour les requêtes courantes
Pour rendre l'expérience API plus agréable pour le consommateur moyen, envisagez de regrouper des ensembles de conditions dans des chemins RESTful facilement accessibles. Par exemple, la requête de tickets récemment fermée ci-dessus pourrait être empaquetée sous la forme
GET /tickets/recently_closed
Exemple d'URL:/rest/{keyword}
Cette URL est un exemple pour les paramètres de chemin. Nous pouvons obtenir ces données d'URL en utilisant @PathParam
.
Exemple d'URL:/rest?keyword=Java&limit=10
Cette URL est un exemple pour les paramètres de requête. Nous pouvons obtenir ces données d'URL en utilisant @Queryparam
.
La segmentation est plus hiérarchique et "jolie" mais peut être limitante.
Par exemple, si vous avez une URL avec trois segments, chacun transmettant différents paramètres pour rechercher une voiture via la marque, le modèle et la couleur:
www.example.com/search/honda/civic/blue
Il s’agit d’une très jolie URL que l’utilisateur final se rappellera plus facilement, mais vous êtes maintenant coincé dans cette structure. Supposons que vous souhaitiez faire en sorte que, lors de la recherche, l'utilisateur puisse rechercher TOUTES les voitures bleues ou TOUTES les voitures Honda Civics? Un paramètre de requête résout ce problème car il donne une paire clé-valeur. Pour que vous puissiez passer:
www.example.com/search?color=blue
www.example.com/search?make=civic
Vous avez maintenant un moyen de référencer la valeur via sa clé - "color" ou "make" dans votre code de requête.
Vous pouvez contourner ce problème en utilisant éventuellement plus de segments pour créer une sorte de structure de valeur clé telle que:
www.example.com/search/make/honda/model/civic/color/blue
J'espère que ça a du sens ..
De manière générale, j'ai tendance à utiliser les paramètres de chemin lorsqu'il existe une "hiérarchie" évidente dans la ressource, telle que:
/region/state/42
Si cette ressource unique a un statut, on pourrait:
/region/state/42/status
Toutefois, si "région" ne fait pas vraiment partie de la ressource exposée, elle appartient probablement à l'un des paramètres de requête, similaire à la pagination (comme vous l'avez mentionné).