Première
Selon RFC 3986 §3.4 (Uniform Resource Identifiers § (Syntaxe Composants) | Recherche
3.4 Requête
Le composant de requête contient des données non hiérarchiques qui, avec les données du composant de chemin d'accès (Section 3.3), servent à identifier une ressource dans la portée du schéma et de l'autorité de dénomination de l'URI (le cas échéant).
Les composants de requête permettent de récupérer des données non hiérarchiques. il y a peu de choses de nature plus hiérarchique qu'un arbre généalogique! Ainsi , que vous pensiez que c'est "REST-y" ou non , pour vous conformer aux formats, protocoles et framework de et pour le développement de systèmes sur Internet, vous ne devez pas utiliser la chaîne de requête pour identifier cette information.
REST n'a rien à voir avec cette définition.
Avant de répondre à vos questions spécifiques, votre paramètre de requête "recherche" est mal nommé. Il serait préférable de traiter votre segment de requête comme un dictionnaire de paires clé-valeur.
Votre chaîne de requête pourrait être définie de manière plus appropriée comme
?first_name={firstName}&last_name={lastName}&birth_date={birthDate}
etc.
Pour répondre à vos questions spécifiques
1) Quelle conception d'API est plus RESTful, et pourquoi? Sémantiquement, ils veulent dire et se comportent de la même manière. La dernière ressource de l'URI est "enfants", ce qui implique que le client opère sur la ressource enfants.
Je ne pense pas que cela soit aussi clair que vous semblez le croire.
Aucune de ces interfaces de ressources n'est RESTful. La principale condition préalable au style architectural RESTful est que les transitions d'état de l'application doivent être communiquées à partir du serveur en tant qu'hypermédia. Les gens ont travaillé sur la structure des URI pour les transformer en quelque sorte "d'URI RESTful", mais la littérature formelle concernant REST a en réalité très peu à dire à ce sujet. Mon opinion personnelle est qu'une grande partie de la méta-désinformation sur REST a été publiée dans le but de briser les vieilles et mauvaises habitudes. (Construire un système véritablement "RESTful" est en fait un peu de travail. L'industrie s'est foutue de "REST" et a répondu à certaines préoccupations orthogonales avec des qualifications et des restrictions absurdes.)
Selon la documentation REST, si vous souhaitez utiliser HTTP comme protocole d'application, vous devez respecter les exigences formelles des spécifications du protocole et vous ne pouvez pas "configurer http en même temps et déclarer que vous utilisez http". ; Si vous allez utiliser des URI pour identifier vos ressources, vous devez vous conformer aux exigences formelles des spécifications relatives aux URI / URL.
Votre question est directement adressée par RFC3986 §3.4, que j'ai liée ci-dessus. En fin de compte, même si un URI conforme est insuffisant pour considérer une API comme "RESTful", si vous voulez que votre système soit réellement "RESTful" et que vous utilisez HTTP et des URI, vous ne pouvez pas identifier les données hiérarchiques par le biais du serveur. chaîne de requête parce que:
3.4 Requête
Le composant de requête contient des données non hiérarchiques.
...c'est aussi simple que ça.
2) Quels sont les avantages et les inconvénients pour chacun en termes de compréhensibilité du point de vue du client et de maintenabilité du point de vue du concepteur.
Les "avantages" des deux premiers sont qu’ils sont sur la bonne voie . Le "contre" du troisième est qu'il semble être complètement faux.
En ce qui concerne vos problèmes de compréhensibilité et de maintenabilité, ceux-ci sont définitivement subjectifs et dépendent du niveau de compréhension du développeur client et des avantages du concepteur. La spécification d'URI est la réponse définitive quant à la manière dont les URI sont censés être formatés. Les données hiérarchiques sont supposées être représentées sur le chemin et avec des paramètres de chemin. Les données non hiérarchiques sont supposées être représentées dans la requête. Le fragment est plus compliqué, car sa sémantique dépend spécifiquement du type de média de la représentation demandée. Donc, pour aborder le composant "compréhensibilité" de votre question, je vais essayer de traduire exactement ce que vos deux premiers URI disent réellement. Ensuite, je tenterai de représenter ce que vous dites que vous essayez d'accomplir avec des adresses URI valides.
Traduction de vos adresses URI textuelles en leur sens sémantique
/myservice/api/v1/grandparents/{grandparentID}/parents/children?search={text}
Ceci dit pour les parents des grands-parents, trouver leur enfant ayant search={text}
ce que vous avez dit avec votre adresse URI n'est cohérent que si vous recherchez les frères et sœurs d'un grand-parent. Avec vos «grands-parents, parents, enfants», vous avez trouvé un «grand-parent», remontant d’une génération à l’autre de ses parents, puis redescendant dans la génération des «grands-parents» en examinant les enfants des parents.
/myservice/api/v1/parents/{parentID}/children?search={text}
Cela indique que pour le parent identifié par {parentID}, trouvez son enfant. ?search={text}
Ceci est plus proche de ce que vous voulez et correspond à une relation parent-> enfant qui peut probablement être utilisée pour modéliser l'intégralité de votre API. Pour le modéliser de cette façon, il incombe au client de reconnaître que s’ils ont un "grandparentId", il existe une couche indirectionnelle entre l’ID qu’ils ont et la partie du graphique de la famille qu’ils souhaitent voir. Pour rechercher un "enfant" par "grandparentId", vous pouvez appeler votre /parents/{parentID}/children
service, puis pour chaque enfant renvoyé, recherchez son identifiant de personne auprès de ses enfants.
Implémentation de vos exigences en tant qu'URI
Si vous souhaitez modéliser un identificateur de ressource plus extensible qui puisse parcourir l'arborescence, je peux penser à différentes façons de le faire.
1) Le premier, auquel j'ai déjà fait allusion. Représente le graphique de "People" sous forme de structure composite. Chaque personne a une référence à la génération située au-dessus d'elle via son chemin de parent et à une génération inférieure à son chemin d'enfants.
/Persons/Joe/Parents/Mother/Parents
serait un moyen d'attraper les grands-parents maternels de Joe.
/Persons/Joe/Parents/Parents
serait un moyen d'attraper tous les grands-parents de Joe.
/Persons/Joe/Parents/Parents?id={Joe.GrandparentID}
prendrait le grand-parent de Joe ayant l'identifiant que vous avez en main.
et tout cela aurait du sens (notez qu'il pourrait y avoir une baisse de performance ici en fonction de la tâche en forçant un DFS sur le serveur en raison d'un manque d'identification de branche dans le modèle "Parents / Parents / Parents".) Vous bénéficiez également d'avoir la capacité de supporter un nombre quelconque de générations. Si, pour une raison quelconque, vous souhaitez rechercher 8 générations, vous pouvez le représenter par
/Persons/Joe/Parents/Parents/Parents/Parents/Parents/Parents/Parents/Parents?id={Joe.NotableAncestor}
mais ceci mène à la deuxième option dominante pour représenter ces données: via un paramètre de chemin.
2) Utiliser les paramètres de chemin pour "interroger la hiérarchie" Vous pouvez développer la structure suivante pour alléger le fardeau des utilisateurs tout en conservant une API cohérente.
Pour regarder en arrière 147 générations, représentant cet identifiant de ressource avec des paramètres de chemin vous permet de faire
/Persons/Joe/Parents;generations=147?id={Joe.NotableAncestor}
Pour localiser Joe à partir de son arrière-grand-parent, vous pouvez consulter le graphique d'un nombre connu de générations pour Joe's Id.
/Persons/JoesGreatGrandparent/Children;generations=3?id={Joe.Id}
Le point important à noter avec ces approches est que sans informations supplémentaires dans l'identifiant et la demande, vous devez vous attendre à ce que le premier URI récupère une personne 147 générations à partir de Joe avec l'identifiant de Joe.NotableAncestor. Vous devez vous attendre à ce que le second récupère Joe. Supposons que vous souhaitiez réellement que votre client appelant puisse récupérer l'ensemble des nœuds et leurs relations entre la personne racine et le contexte final de votre URI. Vous pouvez le faire avec le même URI (avec quelques décorations supplémentaires) et en définissant une acceptation de text/vnd.graphviz
sur votre demande, qui est le type de média enregistré par l'IANA pour la .dot
représentation graphique. Avec cela, changez l’URI en
/Persons/Joe/Parents;generations=147?id={Joe.NotableAncestor.Id}#directed
avec un en-tête de demande HTTP
Accept: text/vnd.graphviz
, vous pouvez faire en sorte que les clients indiquent assez clairement qu'ils veulent le graphe dirigé de la hiérarchie générationnelle entre Joe et 147 générations antérieures, où cette 147e génération ancestrale contient une personne identifiée comme étant "l'Ancêtre notable" de Joe.
Je ne sais pas si text / vnd.graphviz a une sémantique prédéfinie pour son fragment, je ne pourrais pas en trouver dans une recherche d'instruction. Si ce type de média a effectivement des informations de fragment prédéfinies, il convient de suivre sa sémantique pour créer un URI conforme. Toutefois, si ces sémantiques ne sont pas prédéfinies, la spécification d'URI indique que la sémantique de l'identificateur de fragment n'est pas contrainte, mais définie par le serveur, ce qui rend l'utilisation valide.
3) À quoi servent réellement les chaînes de requête, mis à part le "filtrage" de votre ressource? Si vous optez pour la première approche, le paramètre de filtre est intégré à l'URI lui-même en tant que paramètre de chemin d'accès au lieu d'un paramètre de chaîne de requête.
Je pense avoir déjà battu cet homme à mort, mais les chaînes de requête ne servent pas à "filtrer" les ressources. Ils servent à identifier votre ressource à partir de données non hiérarchiques. Si vous avez détaillé votre hiérarchie avec votre chemin en allant
/person/{id}/children/
et que vous souhaitez identifier un enfant spécifique ou un ensemble spécifique d'enfants, utilisez un attribut qui s'applique à l'ensemble que vous identifiez et incluez-le dans la requête.