191 votes

Complexe REST / Composite / Ressources imbriquées

Je suis d'essayer d'envelopper ma tête autour de la meilleure façon d'aborder les concepts d'une API REST. Plat ressources qui ne contiennent pas d'autres ressources ne sont pas un problème. Lorsque je suis en cours d'exécution dans les problèmes sont complexes Ressources.

Par exemple, j'ai une ressource pour ComicBook. ComicBook a toutes sortes de propriétés comme l'auteur, le numéro, la date, etc.

Une bande dessinée a également une liste de 1..n couvre. Ces couvercles sont des objets complexes. Ils contiennent beaucoup d'information à propos de la couverture, l'auteur, la date, et même une image encodée en base 64 de la couverture.

Pour un OBTENIR sur ComicBook je pouvais juste de retour de la bande dessinée, et de toutes les couvertures, y compris leurs base64 ed des images. Ce n'est probablement pas une grosse affaire pour l'obtention d'une seule bande dessinée. Mais supposons que je suis la construction d'une application client qui veut faire la liste de toutes les bandes dessinées dans le système dans un tableau. Le tableau contiendra quelques propriétés de la ComicBook de ressources, mais nous ne sommes certainement pas à afficher toutes les couvertures de la table. De retour de 1000 couvertures, chacun avec plusieurs couvre entraînerait une trop grande quantité de données à venir à travers le fil, de données qui n'est pas nécessaire à l'utilisateur final dans ce cas.

Mon instinct est de faire de la Couverture de ressources et de ComicBook contient couvre. Alors maintenant, la Couverture est un URI. OBTENIR sur la bande dessinée fonctionne maintenant, au lieu de l'énorme Couverture de ressources, nous envoyons un URI pour chaque couverture, et les clients peuvent récupérer la Couverture de ressources comme ils en ont besoin.

Maintenant, j'ai un problème avec la création de nouvelles bandes dessinées. Certes, je vais vous voulez créer au moins un abri quand j'ai créer une bande Dessinée, en fait, c'est probablement une règle d'entreprise. Alors maintenant, je suis coincé, je force les clients à appliquer des règles métier par la première soumission d'un Couvercle, l'obtention de l'URI pour cette couverture, puis l'Affichage d'un ComicBook avec URI dans la liste, ou mon POST sur ComicBook prend en un autre à la recherche de Ressources qu'il crache. Les ressources entrants pour le POST et GET sont profondes des copies, où le sortant Obtient contenir des références à des ressources dépendantes.

La Couverture de ressources sera probablement nécessaire en tout cas, car je suis sûr que tant que client, je veux l'adresse Couvre sens dans certains cas. Donc, le problème existe dans une forme générale quelle que soit la taille de la ressource dépendante. En général, comment gérez-vous des Ressources complexes sans forcer le client à juste "savoir" de la manière dont ces ressources sont composées?

70voto

Alex Points 1864

@ray, excellente discussion

@jgerman, n'oubliez pas que juste parce que c'est le REPOS, ne signifie pas que les ressources doivent être fixés dans la pierre de son POSTE.

Ce que vous choisissez d'inclure dans la représentation d'une ressource est à vous.

Votre cas de la le couvre référencé séparément est simplement la création d'un parent de ressources (bande dessinée) dont l'enfant des ressources (couvre) peuvent être croisées. Par exemple, vous pourriez aussi envisager de fournir des références à des auteurs, des éditeurs , des caractères ou des catégories séparément. Vous pouvez créer ces ressources ou séparément avant de la bande dessinée qui fait que l'enfant ressources. Alternativement, vous pouvez créer de nouveaux enfants ressources lors de la création de ressources pour les parents.

Votre cas spécifique de la couverture est légèrement plus complexe que le couvercle n'a vraiment besoin d'un livre de bande dessinée, et vice-versa.

Toutefois, si vous pensez à un message électronique en tant que ressource, et la traiter comme une enfant de ressource, vous pouvez évidemment toujours de référence, l'adresse séparément. Par exemple, obtenir toutes les adresses. Ou, créer un nouveau message avec une précédente à partir de l'adresse. Si l'e-mail a été de REPOS, vous peut facilement voir que de nombreux renvois des ressources qui pourraient être disponibles: /réception de messages /projet-messages, /de-adresses, /pour-les adresses, les adresses, /sujets /pièces jointes, /dossiers /balises /catégories /les étiquettes, et al.

Ce tutoriel fournit un excellent exemple de la croix-ressources référencées. http://www.peej.co.uk/articles/restfully-delicious.html

C'est le modèle le plus courant pour générées automatiquement les données. Par exemple, vous ne publiez pas un URI, ID, ou la date de création de la nouvelle ressource, que celles-ci sont générées par le serveur. Et pourtant, vous pouvez récupérer l'URI, ID, ou la date de création lorsque vous obtenez la nouvelle ressource en arrière.

Un exemple dans votre cas de données binaires. Par exemple, vous souhaitez publier des données binaires comme des enfants ressources. Lorsque vous obtenez les ressources pour les parents, vous pouvez représenter les enfants de ressources que les mêmes données binaires, ou comme les Uri qui représentent les données binaires.

Les formes et les paramètres sont déjà différente de la représentation HTML de ressources. Affichage binaire/fichier de paramètre qui donne une URL n'est pas un étirement.

Lorsque vous obtenez la forme d'une nouvelle ressource (/bandes dessinées/nouveau), ou d'obtenir le formulaire pour modifier une ressource (/bandes dessinées/0/modifier), vous vous demandez quels sont les formes spécifiques de représentation de la ressource. Si vous le poster de la collection de ressources avec un contenu de type "application/x-www-form-urlencoded" ou "multipart/form-data", vous demandez au serveur pour enregistrer ce type de représentation. Le serveur peut répondre avec la représentation HTML qui a été enregistré, ou que ce soit.

Vous pouvez également permettre une HTML, XML ou JSON représentation pour être affecté à la collecte de ressources, pour les fins d'une API ou similaire.

Il est également possible de représenter vos ressources et de flux de travail comme vous le décrivez, en tenant compte de couvre posté après la bande dessinée, mais exigeant de la bande dessinée d'avoir une couverture. Exemple comme suit.

  • Permet de retard de couverture de la création
  • Permet la création de bd avec couverture
  • Permet couvre pour être référencé
  • Permet à plusieurs couvre
  • Création d'un projet de bande dessinée
  • Création d'un projet de couvertures de bandes dessinées
  • Publier le projet de bande dessinée

GET /bandes dessinées
=> 200 OK, tous les livres de bandes dessinées.

GET /bandes dessinées/0
=> 200 OK, bande dessinée (id: 0) avec des couvertures (/covers/1, /covers/2).

GET /bandes dessinées/0/couvre
=> 200 OK, je me couvre pour la bande dessinée (id: 0).

GET /couvre
=> 200 OK, tous les couvercles.

GET /covers/1
=> 200 OK, couverture (id: 1) avec la bande dessinée (/bandes dessinées/0).

GET /bandes dessinées/nouvelle
=> 200 OK, Obtenir le formulaire pour créer des bandes dessinées (forme: POST /projet de comic-books).

POST /projet de comic-books
title=foo
auteur=boo
publisher=goo
publié=2011-01-01
=> 302 Found, Emplacement: /projet de comic-books/3, de Rediriger le projet de bande dessinée (id: 3), avec des couvertures (en binaire).

GET /projet de comic-books/3
=> 200 OK, projet de bande dessinée (id: 3), avec des couvertures.

GET /projet de bande-dessinée-livres/3/couvre
=> 200 OK, je me couvre pour un projet de bande dessinée (/projet-de bande dessinée/3).

GET /projet de bande-dessinée-livres/3/covers/nouvelle
=> 200 OK, Obtenir le formulaire pour créer une jaquette pour un projet de bande dessinée (/projet-de bande dessinée/3) (forme: POST /projet de bande-dessinée-livres/3/couvertures).

POST /projet de bande-dessinée-livres/3/couvre
cover_type=avant
cover_data=(binaire)
=> 302 Found, Emplacement: /draft-bd-livres/3/couvre, Rediriger vers la nouvelle couverture pour le projet de bande dessinée (/projet-de bande dessinée/3/covers/1).

GET /projet de bande-dessinée-livres/3/publier
=> 200 OK, Obtenir le formulaire de publier le projet de bande dessinée (id: 3) (forme: POST /publié comic-books).

POST /publié des bandes dessinées
title=foo
auteur=boo
publisher=goo
publié=2011-01-01
cover_type=avant
cover_data=(binaire)
=> 302 Found, Emplacement: /bandes dessinées/3, Rediriger à la publication de bande dessinée (id: 3), avec des couvertures.

50voto

Ray Toal Points 35382

Le traitement de housses de ressources est certainement dans l'esprit de REPOS, surtout HATEOAS. Donc oui, un GET demande http://example.com/comic-books/1 vous donnent une représentation du livre 1, avec des propriétés, y compris un ensemble d'Uri pour les couvertures. So far So good.

Votre question est que la façon de traiter avec la bande dessinée de création. Si votre entreprise règle était qu'un livre qui aurait 0 ou plusieurs couvertures, alors vous n'avez pas de problème:

POST http://example.com/comic-books

avec coverless de bande dessinée de données permettra de créer une nouvelle bande dessinée et de ramener le serveur d'identification généré (permet de dire qu'il revient à 8), et maintenant vous pouvez ajouter couvre à elle de la sorte:

POST http://example.com/comic-books/8/covers

avec le couvercle dans le corps de l'entité.

Maintenant, vous avez une bonne question qui est-ce qui se passe si votre entreprise règle dit qu'il y a toujours au moins un couvercle. Voici quelques choix, le premier dont vous avez identifié dans votre question:

  1. La Force de la création d'une couverture tout d'abord, maintenant essentiellement à couvrir un non-dépendante de la ressource, ou vous placez la première de couverture dans le corps de l'entité de la POSTE qui crée la bande dessinée. Ce que vous dites signifie que la représentation que vous publiez à créer sera différente de la représentation que vous OBTENEZ.

  2. Définir la notion de primaire ou initiale, ou privilégiées, ou autrement désignés de couverture. C'est probablement une modélisation de hack, et si vous n'avez que ce serait comme de peaufiner votre modèle d'objet (votre conceptuel ou de modèle d'affaires) afin de s'adapter à une technologie. Pas une bonne idée.

Vous devriez peser ces deux choix contre le fait qu'elle permet coverless comics.

Qui des trois choix devriez-vous prendre? Ne sachant pas trop à propos de votre situation, mais de répondre à la générale 1..N de ressources dépendant de la question, je dirais:

  • Si vous pouvez aller à 0..N pour votre service RESTful couche, grande. Peut-être une couche entre votre Réparateur SOA peut traiter le plus de contrainte si au moins un est requis. (Pas sûr de savoir comment ce serait de regarder, mais il pourrait être intéressant d'étudier.... les utilisateurs finaux n'ont pas l'habitude de voir de l'aoc, de toute façon.)

  • Si vous désirez tout simplement un modèle 1..N contrainte, puis demandez-vous si les couvre peut-être partageable ressources, en d'autres termes, ils peuvent exister sur d'autres choses que de la bande dessinée. Maintenant, ils ne sont pas dépendants de ressources et vous pouvez les créer en premier et l'approvisionnement des Uri dans votre POST qui crée des bandes dessinées.

  • Si vous avez besoin d'1..N et couvre restent dépendants, détendez-vous simplement à votre instinct pour garder les représentations dans le POST et OBTENIR la même, ou en faire de même.

Le dernier élément est expliqué comme suit:

<comic-book>
  <name>...</name>
  <edition>...</edition>
  <cover-image>...BASE64...</cover-image>
  <cover-image>...BASE64...</cover-image>
  <cover>...URI...</cover>
  <cover>...URI...</cover>
 </comic-book>`

Lorsque vous postez vous permettre existant uri, si vous en avez (emprunté à d'autres livres), mais aussi dans une ou plusieurs images initiales. Si vous êtes à la création d'un livre et de votre entité a pas de couverture d'image, de retour d'un 409 ou similaire réponse. Sur OBTENIR vous pouvez retourner les Uri..

Donc, fondamentalement, vous êtes en permettant à la POSTE et d'OBTENIR des représentations de "la même" mais vous venez de choisir de ne pas "utiliser" de l'image à OBTENIR et ne la couvrez pas sur le POST. L'espoir qui fait sens.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X