Je recherche un moyen raisonnable de représenter les recherches en tant qu'URL RESTful.
La configuration: j'ai deux modèles, Cars et Garages, où les voitures peuvent être dans les garages. Donc mes URL ressemblent à:
/car/xxxx
xxx == car id
returns car with given id
/garage/yyy
yyy = garage id
returns garage with given id
Une voiture peut exister par elle-même (d'où la / voiture), ou elle peut exister dans un garage. Quelle est la bonne façon de représenter, disons, toutes les voitures d'un garage donné? Quelque chose comme:
/garage/yyy/cars ?
Que diriez-vous de l'union des voitures dans le garage yyy et zzz?
Quelle est la bonne façon de représenter une recherche de voitures avec certains attributs? Dites: montrez-moi toutes les berlines bleues à 4 portes:
/car/search?color=blue&type=sedan&doors=4
ou devrait-il plutôt être / cars?
L'utilisation de la «recherche» semble inappropriée là-bas - quel est le meilleur moyen / terme? Faut-il que ce soit:
/cars/?color=blue&type=sedan&doors=4
Les paramètres de recherche doivent-ils faire partie de PATHINFO ou QUERYSTRING?
En bref, je recherche des conseils pour la conception d'URL REST entre modèles et pour la recherche.
[Mise à jour] J'aime la réponse de Justin, mais il ne couvre pas le cas de recherche multi-champs:
/cars/color:blue/type:sedan/doors:4
ou quelque chose comme ça. Comment allons-nous
/cars/color/blue
au cas à champs multiples?
/cars
et/car
n'est pas sémantique et donc une mauvaise idée. Utilisez toujours le pluriel lorsqu'il y a plus d'un élément dans cette catégorie.Réponses:
Pour la recherche, utilisez des chaînes de requête. C'est parfaitement RESTful:
Un avantage des chaînes de requête régulières est qu'elles sont standard et largement comprises et qu'elles peuvent être générées à partir de form-get.
la source
/cars?color=whatever
./cars?color=blue&type=sedan&doors=4/engines
, ne fonctionnera pas/cars?param=value
est pour un filtrage simple sur la liste des voitures et/cars/search?param=value
pour créer une recherche (avec ou sans persistance) où le résultat peut contenir un score de recherche, une catégorisation, etc. Vous pouvez également créer / supprimer une recherche nommée comme/cars/search/mysearch
. Regardez ça: stackoverflow.com/a/18933902/1480391La jolie conception d'URL RESTful consiste à afficher une ressource basée sur une structure (structure de type répertoire, date: articles / 2005/5/13, objet et ses attributs, ..), la barre oblique
/
indique une structure hiérarchique, utilisez-id
plutôt la.Structure hiérarchique
Je préférerais personnellement:
Si un utilisateur supprime la
/car-id
partie, il apporte l'cars
aperçu - intuitif. L'utilisateur sait exactement où il se trouve dans l'arbre, qu'est-ce qu'il regarde. Il sait dès le premier regard que les garages et les voitures sont en relation./car-id
indique également qu'il appartient ensemble contrairement à/car/id
.Recherche
La requête de recherche est OK telle quelle , il n'y a que votre préférence, ce qui doit être pris en compte. La partie amusante survient lors de la jointure de recherches (voir ci-dessous).
Ou fondamentalement tout ce qui n'est pas une barre oblique comme expliqué ci-dessus.
La formule
/cars[?;]color[=-:]blue[,;+&]
:, * bien que je n'utiliserais pas le&
signe car il n'est pas reconnaissable dans le texte à première vue.Listes d'options
fonctionnalités possibles?
Annulez les chaînes de recherche (!)
Pour rechercher des voitures, mais pas en noir et rouge :
?color=!black,!red
color:(!black,!red)
Recherches jointes
Rechercher des voitures rouges ou bleues ou noires avec 3 portes dans les garages id 1..20 ou 101..103 ou 999 mais pas 5
/garage[id=1-20,101-103,999,!5]/cars[color=red,blue,black;doors=3]
Vous pouvez ensuite construire des requêtes de recherche plus complexes. (Regardez la correspondance d'attributs CSS3 pour l'idée de faire correspondre les sous-chaînes. Par exemple, recherche d'utilisateurs contenant "bar"
user*=bar
.)Conclusion
Quoi qu'il en soit, cela pourrait être la partie la plus importante pour vous, car vous pouvez le faire comme vous le souhaitez, gardez à l'esprit que l' URI RESTful représente une structure qui est facilement compréhensible, par exemple
/directory/file
, comme un répertoire,,/collection/node/item
dates/articles/{year}/{month}/{day}
.. Et lorsque vous omettez l'un des derniers segments, vous savez immédiatement ce que vous obtenez.Alors .., tous ces caractères sont autorisés non encodés :
a-zA-Z0-9_.-~
généralement autorisé à la fois codé et non, les deux utilisations sont alors équivalentes.
$-_.+!*'(),
;/?:@=&
peut être utilisé non codé aux fins qu'il représente, sinon il doit être codé.
dangereux:
<>"#%{}|\^~[]`
pourquoi dangereux et pourquoi devrait être plutôt encodé: RFC 1738 voir 2.2
Voir également RFC 1738 # page-20 pour plus de classes de caractères.
RFC 3986 voir 2.2
Malgré ce que j'ai dit précédemment, voici une distinction courante des délimètres, ce qui signifie que certains "sont" plus importants que d'autres.
:/?#[]@
!$&'()*+,;=
Pour en savoir plus:
Hiérarchie: voir 2.3 , voir 1.2.3
syntaxe du paramètre de chemin url
Attribut CSS3 correspondant à
IBM: services Web RESTful - Notions de base
Remarque: RFC 1738 a été mis à jour par RFC 3986
la source
POST
. De plus, d'autres idées que vous avez données dans votre réponse sont également très appréciables. Merci beaucoup!;
par opposition à la&
lisibilité? Parce que si c'est le cas, je pense que je préférerais en fait le&
car c'est le délimiteur le plus courant ... non? :) Merci!&
le délimiteur n'est connu que des développeurs. Les parents, les grands-parents et la population non éduquée acceptent les délimiteurs tels qu'ils sont utilisés dans les textes écrits courants.Bien que le fait d'avoir les paramètres sur le chemin présente certains avantages, il y a, à l'OMI, certains facteurs supérieurs
Tous les caractères nécessaires à une requête de recherche ne sont pas autorisés dans une URL. La plupart des signes de ponctuation et Unicode devraient être encodés en URL en tant que paramètre de chaîne de requête. Je lutte avec le même problème. Je voudrais utiliser XPath dans l'URL, mais toutes les syntaxes XPath ne sont pas compatibles avec un chemin URI. Ainsi, pour les chemins simples, il
/cars/doors/driver/lock/combination
serait approprié de localiser l'combination
élément ' ' dans le document XML de la porte du conducteur. Mais ce/car/doors[id='driver' and lock/combination='1234']
n'est pas si sympa.Il existe une différence entre le filtrage d'une ressource en fonction de l'un de ses attributs et la spécification d'une ressource.
Par exemple, depuis
/cars/colors
renvoie une liste de toutes les couleurs pour toutes les voitures (la ressource retournée est une collection d'objets de couleur)/cars/colors/red,blue,green
renvoie une liste d'objets de couleur rouge, bleu ou vert, et non une collection de voitures.Pour rendre les voitures, le chemin serait
/cars?color=red,blue,green
ou/cars/search?color=red,blue,green
Les paramètres du chemin sont plus difficiles à lire car les paires nom / valeur ne sont pas isolées du reste du chemin, qui n'est pas une paire nom / valeur.
Un dernier commentaire. Je préfère
/garages/yyy/cars
(toujours au pluriel) à/garage/yyy/cars
(c'était peut-être une faute de frappe dans la réponse originale) car cela évite de changer le chemin entre le singulier et le pluriel. Pour les mots avec un «s» ajouté, le changement n'est pas si mauvais, mais le passage/person/yyy/friends
à/people/yyy
semble lourd.la source
Pour développer la réponse de Peter - vous pouvez faire de la recherche une ressource de première classe:
La ressource de recherche aurait des champs pour la couleur, le modèle de fabrication, l'état garaged, etc. et pourrait être spécifiée en XML, JSON ou tout autre format. Comme la ressource Car and Garage, vous pouvez restreindre l'accès aux recherches en fonction de l'authentification. Les utilisateurs qui exécutent fréquemment les mêmes recherches peuvent les stocker dans leurs profils afin qu'ils n'aient pas besoin d'être recréés. Les URL seront suffisamment courtes pour que dans de nombreux cas, elles puissent être facilement échangées par e-mail. Ces recherches stockées peuvent être à la base de flux RSS personnalisés, etc.
Il existe de nombreuses possibilités d'utilisation des recherches lorsque vous les considérez comme des ressources.
L'idée est expliquée plus en détail dans ce Railscast .
la source
La réponse de Justin est probablement la voie à suivre, bien que dans certaines applications, il puisse être judicieux de considérer une recherche particulière comme une ressource à part entière, comme si vous souhaitez prendre en charge les recherches enregistrées nommées:
ou
la source
J'utilise deux approches pour implémenter les recherches.
1) Cas le plus simple, pour interroger les éléments associés et pour la navigation.
Cela signifie, interrogez les voitures dont l'ID de garage est égal à 1.
Il est également possible de créer des recherches plus complexes:
Voitures dans tous les garages de FirstStreet qui ne sont pas rouges (3e page, 100 éléments par page).
2) Les requêtes complexes sont considérées comme des ressources régulières créées et récupérables.
Le corps POST pour la création de recherche est le suivant:
Il est basé sur Grails (critères DSL): http://grails.org/doc/2.4.3/ref/Domain%20Classes/createCriteria.html
la source
Ce n'est pas REST. Vous ne pouvez pas définir d'URI pour les ressources à l'intérieur de votre API. La navigation dans les ressources doit être basée sur l'hypertexte. C'est bien si vous voulez de jolis URI et de grandes quantités de couplage, mais ne l'appelez pas simplement REST, car il viole directement les contraintes de l'architecture RESTful.
Voir cet article de l'inventeur de REST.
la source
Bien que j'aime la réponse de Justin, je pense qu'elle représente plus précisément un filtre plutôt qu'une recherche. Et si je veux en savoir plus sur les voitures dont le nom commence par cam?
De la façon dont je le vois, vous pouvez l'intégrer dans la façon dont vous gérez des ressources spécifiques:
/ cars / cam *
Ou, vous pouvez simplement l'ajouter dans le filtre:
/ cars / doors / 4 / name / cam * / colors / red, bleu, vert
Personnellement, je préfère ce dernier, mais je ne suis en aucun cas un expert en REST (j'en ai entendu parler il y a seulement 2 semaines environ ...)
la source
/cars?name=cam*
RESTful ne recommande pas d'utiliser des verbes dans les URL / voitures / la recherche n'est pas reposante. La bonne façon de filtrer / rechercher / paginer vos API consiste à utiliser les paramètres de requête. Cependant, il peut arriver que vous deviez enfreindre la norme. Par exemple, si vous effectuez une recherche sur plusieurs ressources, vous devez utiliser quelque chose comme / search? Q = query
Vous pouvez consulter http://saipraveenblog.wordpress.com/2014/09/29/rest-api-best-practices/ pour comprendre les meilleures pratiques de conception des API RESTful.
la source
De plus, je suggérerais également:
Ici,
Search
est considéré comme une ressource enfant deCars
ressource.la source
Il y a beaucoup de bonnes options pour votre cas ici. Vous devriez toujours envisager d'utiliser le corps POST.
La chaîne de requête est parfaite pour votre exemple, mais si vous avez quelque chose de plus compliqué, par exemple une longue liste arbitraire d'éléments ou des conditions booléennes, vous voudrez peut-être définir la publication comme un document, que le client envoie via POST.
Cela permet une description plus flexible de la recherche et évite la limite de longueur d'URL du serveur.
la source
Mon conseil serait le suivant:
Éditer:
J'espère que cela vous donne l'idée. Essentiellement, votre API Rest devrait être facilement détectable et devrait vous permettre de parcourir vos données. Un autre avantage de l'utilisation des URL et non des chaînes de requête est que vous pouvez tirer parti des mécanismes de mise en cache natifs qui existent sur le serveur Web pour le trafic HTTP.
Voici un lien vers une page décrivant les maux des chaînes de requête dans REST: http://web.archive.org/web/20070815111413/http://rest.blueoxen.net/cgi-bin/wiki.pl?QueryStringsConsideredHarmful
J'ai utilisé le cache de Google parce que la page normale ne fonctionnait pas pour moi, voici également ce lien: http://rest.blueoxen.net/cgi-bin/wiki.pl?QueryStringsConsideredHarmful
la source
/cars/colors/red,blue,green
et/cars/colors/green,blue,red
? L'élément path de l'URI devrait être hiérarchique, et je ne vois pas vraiment que ce soit le cas ici. Je pense que c'est une situation où la chaîne de requête est le choix le plus approprié.