Quelle est la meilleure structure d'URL RESTful pour une ressource récursive?

10

Je crée un service RESTfull pour une structure de ressource arborescente et je me demandais quelle serait la meilleure structure d'URL?

J'ai trois exigences:

  1. pouvoir obtenir une collection de ressources racine
  2. pouvoir obtenir une ressource individuelle
  3. être en mesure d'obtenir une collection de ressources pour les enfants

Ma pensée actuelle est:

/rest/documents
/rest/documents/{id}
/rest/documents/{id}/documents

Je pensais également à emprunter les routes singulier / pluriel pour désigner des listes ou des éléments individuels, mais je sais que je vais avoir une ressource qui est au même pluriel qu'au singulier, donc décidé contre cela.

Quelqu'un at-il des réflexions sur ce qui précède? ou avez-vous une façon différente / meilleure de structurer cela?

Matt Brailsford
la source
Je peux mal comprendre la question, mais comme nous parlons d'URL, le référencement est-il un problème?
Jon Hopkins
Le référencement n'est pas un problème, non. Je demande essentiellement la meilleure structure d'URL logique pour une ressource d'auto-référencement.
Matt Brailsford
Cela me semble assez simple.
Tim Post
Jusqu'où cette structure peut-elle aller?
Martijn Verburg
@Martijn la profondeur n'est pas restreinte
Matt Brailsford

Réponses:

11

Ce qui me vient à l'esprit est: ne laissez pas l'API RESTful refléter la récursivité dans l'URL elle-même. À bien y penser, votre ressource n'est que les documents.

Si vos documents sont stockés physiquement conformément à la structure récursive, créez un mappage vers un ID unique et utilisez l'ID dans l'URL:

/rest/documents/{id}

Maintenant, si vous avez vos documents comme celui-ci:

| DocumentName | DocumentPath | DocumentID |
--------------------------------------------
| abc | / abc | 1 |
| asd | / abc / asd | 2 |
| asd | / asd | 3 |
| boo | / abc / asd / boo | 4 |
| hé | / abc / asd / hey | 5 |

la demande consulterait cette URL pour le /abc/asddocument

GET /rest/documents/2

Donc, vous devez maintenant fournir aux utilisateurs de votre API les moyens de parcourir votre structure avec peu d'effort. Cela pourrait être fait en enveloppant votre charge utile de réponse (document) dans un objet, contenant des informations de parcours supplémentaires, comme ceci:

{
   data: { /* your document goes here */ },
   parent: {"abc": 1 },
   children: [ { "boo": 4 }, { "hey": 5} ]
}

à condition que vous vous attendiez à ce que les utilisateurs ne créent pas trop de documents dans un seul niveau, vous pouvez inclure une liste d'enfants dans la réponse. Si ce n'est pas le cas, vous pouvez proposer à l'utilisateur de récupérer les ID de document enfant de cette manière, en permettant par exemple de paginer les résultats via les paramètres de la chaîne de requête:

GET /rest/documents/2/children?page=2&size=50

Enfin, en parlant des paramètres de la chaîne de requête, vous pouvez également fournir les informations de chemin directement via les paramètres de la chaîne de requête:

GET /rest/documents?path=somepath&page=1&size=42

Toutes les approches mentionnées s'attendent à ce que la plaine GET /rest/documentsrenvoie uniquement les documents racine.

netchkin
la source
1
Bonne idée. Cependant, la relation avec les documents enfants n'est pas claire à partir de l'API si les documents enfants sont inclus dans la réponse pour un document. Si les documents ont également une autre sous-ressource, par exemple des commentaires, vous accéderez généralement aux questions d'un document en utilisant / documents / {id} / questions. Pour être cohérent et clarifier la relation avec les documents enfants dans l'API, je suggère que les documents enfants soient accessibles par / documents / {id} / child-documents. Les représentations retournées seraient des Documents comme / documents / {id}. Donc, le reste de ce que vous avez décrit ici fonctionne toujours aussi.
Nathan Ward
2

Quelque chose comme ça peut-être:

/rest/{rootEntity}/Item/{leafEntity}/{id}
/rest/{entity}/ItemList
/rest/{entity}/ItemList/{leafEntity}

où {rootEntity} est le point de départ de votre collection, {leafEntity} est n'importe quel nœud feuille nommé dans votre arborescence.

Vous pouvez ajouter quelques paramètres ci-dessus pour sélectionner, par exemple, Dernier ou Tout ou quelque chose.

Gary Rowe
la source