Quand dois-je utiliser les paramètres de chemin par rapport aux paramètres de requête dans une API RESTful?


141

Je veux rendre mon API RESTful très prévisible. Quelle est la meilleure pratique pour décider quand effectuer une segmentation des données en utilisant l'URI plutôt qu'en utilisant des paramètres de requête.

Il est logique pour moi que les paramètres système qui prennent 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?


1
une question similaire est répondue ici ... stackoverflow.com/questions/3198492/…
Lalit Mehra

Réponses:


239

La meilleure pratique pour la conception d'API RESTful est que les paramètres de chemin sont utilisés pour identifier une ou plusieurs ressources spécifiques, tandis que les paramètres de requête sont utilisés pour trier / filtrer ces ressources.

Voici un exemple. Supposons que vous implémentiez des points de terminaison d'API RESTful pour une entité appelée Car. Vous structureriez vos points de terminaison comme ceci:

GET /cars
GET /cars/:id
POST /cars
PUT /cars/:id
DELETE/cars/:id

De cette façon, vous n'utilisez les paramètres de chemin que lorsque vous spécifiez la ressource à récupérer, mais cela ne trie / filtre en aucune façon les ressources.

Supposons maintenant que vous vouliez ajouter la possibilité de filtrer les voitures par couleur dans vos demandes GET. Étant donné que 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 effectue cette opération. Vous ajouteriez ce paramètre de requête à votre requête GET/cars comme ceci:

AVOIR /cars?color=blue

Ce point de terminaison 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 tous en minuscules. Si vous avez un nom d'entité qui est généralement composé de deux mots en anglais, vous utiliseriez un trait d'union pour séparer les mots, pas la casse de chameau.

Ex. /two-words


3
Merci pour votre réponse Mike. Il s'agit d'une méthodologie claire et simple; vaut un vote de ma part. Pourtant, souvent, les développeurs optent pour l'approche `` voitures / bleu '', je me demande quel est leur raisonnement pour le faire ... peut-être décident-ils de créer des paramètres de chemin pour les champs obligatoires, ou peut-être le font-ils pour indiquer que la base de données est partitionnée par ce fragment.
cosbor11

1
Je ne sais pas quel est leur raisonnement. Honnêtement, je ne suis pas d'accord avec cela. Je pense que suivre les conventions et rester simple est le plus logique. Ce faisant, vous permettez aux consommateurs de votre API de mieux comprendre exactement ce qu'ils doivent faire pour accéder à ses fonctionnalités.
Mike

3
qu'en est-il de / cars? id = 1 & color = blue au lieu de cars / 1 /? color = blue. vous
filtrez

1
Faux car la voiture avec id 1 n'existe qu'une seule mais les voitures de couleur bleue peuvent être nombreuses. Il y a la distinction entre identité et filtre
paul

1
Mon hypothèse sur la raison pour laquelle l'utilisation des paramètres de chemin est si répandue est que de nombreux développeurs ont appris des frameworks conçus par des personnes qui ne maîtrisaient pas bien les principes REST (Ruby on Rails en particulier.)
Chris Broski

58

La manière fondamentale de penser à ce sujet est la suivante:

Un URI est un identificateur 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 certain type) a un ensemble d'attributs qui sont soit invariants dans le temps, soit temporels.

Dans l'exemple ci-dessus, une voiture est un objet très tangible qui a des attributs comme la marque, le modèle et le NIV - qui ne change 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 est changée en 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 juste la couleur qui a changé. Avoir plusieurs URI pointant vers la même instance d'objet vous obligera à créer plusieurs gestionnaires d'URI - ce n'est pas une conception efficace, et n'est bien sûr pas intuitive.

Par conséquent, l'URI ne doit être constitué que de parties qui ne changeront jamais et continueront à identifier de manière unique cette ressource tout au long de sa durée de vie. Tout ce qui peut changer doit être réservé aux paramètres de requête, en tant que tels:

GET /cars/honda/civic/coupe/{vin}?color={black}

En bout de ligne, pensez au polymorphisme.


2
Paradigme intéressant. Est-ce un modèle de conception couramment utilisé? Pouvez-vous fournir des API qui utilisent cela dans leur documentation ou des références qui décrivent cette stratégie?
cosbor11

1
J'aime la façon dont vous avez souligné "TYPE" lorsque vous avez écrit "Un URI est un identifiant de ressource qui identifie de manière unique une instance spécifique d'un TYPE de ressource". Je pense que c'est une distinction importante.
jrahhali

15

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é des URI fait allusion à une incompréhension de l'architecture RESTful. Cela suppose qu'un client doit construire lui-même des URI, ce qu'il ne devrait vraiment pas avoir à faire.

Cependant, je suppose que vous ne créez pas une véritable API REST, mais une API `` inspirée de REST '' (comme celle de Google Drive). Dans ces cas, la règle d'or est «path params = resource identification» et «query params = resource sorting». Alors, la question devient, pouvez-vous identifier de manière unique votre ressource SANS statut / région? Si oui, alors c'est peut-être un paramètre de requête. Si non, alors c'est un paramètre de chemin.

HTH.


11
Je ne suis pas d'accord, une bonne API doit être prévisible; RESTful ou autre.
cosbor11

3
Je le pense. Il devrait y avoir des rimes et des raisons sur la façon dont l'URI est formé, plutôt que de nommer arbitrairement les points de terminaison. Quand on peut écrire intuitivement un client API sans constamment référencer la documentation, vous avez écrit une bonne API à mon avis.
cosbor11

2
"Quand on peut écrire intuitivement un client API sans se référer constamment à la documentation". C'est là que je pense que notre compréhension de REST diffère ... le client API ne devrait jamais avoir besoin de «créer» une URL. Ils doivent le sélectionner à partir de la réponse de l'appel d'API précédent. Si vous prenez un site Web par analogie ... Vous allez sur facebook.com, puis vous sélectionnez un lien vers la page des événements. Vous ne vous souciez pas de savoir si l'URL des événements facebook est «prévisible», car vous ne la saisissez pas. Vous y accédez via des liens hypermédia. La même chose est vraie pour une API REST. Alors, rendez les URI significatifs pour vous (le serveur), mais pas pour le client
Oliver McPhee

2
Note ajoutée. Cela ne signifie pas que les URI ne doivent pas suivre un modèle facile à comprendre, cela signifie simplement que ce n'est pas une contrainte d'une API RESTful. Le plus gros problème avec cette zone est que les gens supposent qu'un client doit créer lui-même les URL. Ils ne devraient pas, car cela crée un couplage entre le client et le serveur qui ne devrait pas exister. (par exemple, le serveur ne peut pas modifier une URL sans interrompre toutes les applications clientes). Dans une API REST, le serveur peut les modifier à sa guise.
Oliver McPhee

3
+1 pour l'utilisation des mots suivants: "'path params = resource identification' et 'query params = resource sorting'". Cela m'a vraiment éclairci.
Doug le

3

Une fois, j'ai conçu une API qui était la ressource principale people. Habituellement, les utilisateurs demandaient filtré, peopledonc, pour empêcher les utilisateurs d'appeler quelque chose comme à /people?settlement=urbanchaque fois, j'ai mis en œuvre /people/urbance qui m'a permis plus tard d'ajouter facilement /people/rural. Cela permet également d'accéder à la /peopleliste complète si elle serait utile plus tard. Bref, mon raisonnement était d'ajouter un chemin vers des sous-ensembles communs

D' ici :

Alias ​​pour les requêtes courantes

Pour rendre l'expérience de l'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és ci-dessus peut être regroupée sous la formeGET /tickets/recently_closed


1

De manière générale, j'ai tendance à utiliser des paramètres de chemin lorsqu'il existe une `` hiérarchie '' évidente dans la ressource, telle que:

/region/state/42

Si cette seule ressource a un statut, on pourrait:

/region/state/42/status

Cependant, 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é).


0

La segmentation est plus hiérarchisée et "jolie" mais peut être limitative.

Par exemple, si vous avez une URL avec trois segments, chacun passant des paramètres différents pour rechercher une voiture via la marque, le modèle et la couleur:

www.example.com/search/honda/civic/blue

C'est une très jolie URL et plus facilement mémorisable par l'utilisateur final, mais maintenant vous êtes coincé avec cette structure. Dites que vous voulez faire en sorte que dans la recherche, l'utilisateur puisse rechercher TOUTES les voitures bleues, ou TOUTES les Honda Civics? Un paramètre de requête résout ce problème car il donne une paire clé / valeur. Vous pourriez donc réussir:

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é - soit "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é comme:

www.example.com/search/make/honda/model/civic/color/blue

J'espère que cela a du sens.


-2

Exemple d'URL: /rest/{keyword}

Cette URL est un exemple de paramètres de chemin. Nous pouvons obtenir ces données URL en utilisant @PathParam.

Exemple d'URL: /rest?keyword=java&limit=10

Cette URL est un exemple de paramètres de requête. Nous pouvons obtenir ces données URL en utilisant @Queryparam.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.