0

Je voudrais savoir quelle est la meilleure pratique lorsque vous avez une ressource qui contient une liste de sous-ressources. Par exemple, vous avez la ressource Auteur qui contient des informations telles que le nom, l'identifiant, l'anniversaire et une liste de livres. Cette liste de livres n'existe qu'en relation avec l'auteur. Ainsi, vous avez le scénario suivant:REST conception pour mettre à jour/ajouter/supprimer des éléments d'une liste de sous-ressources

  1. Vous souhaitez ajouter un nouveau livre à la liste des livres
  2. Vous souhaitez mettre à jour le nom d'un livre dans la liste
  3. Vous voulez supprimer un livre de la liste

SOLUTION 1

Je recherche qui est la conception correcte et je l'ai trouvé plusieurs approches. Je veux savoir s'il existe une façon standard de concevoir cela. Je pense que la conception du livre, il dit avoir les méthodes suivantes:

  1. ajouter: POST /authors/{authorId}/book/
  2. Pour mettre à jour: PUT /authors/{authorId}/book/{bookId}
  3. Pour supprimer: DELETE /authors/{authorId}/book/{bookId}

SOLUTION 2

Ma solution est d'avoir une seule méthode PUT qui fait toutes ces 3 choses parce que la liste des livres existe seulement à l'intérieur de l'auteur de l'objet et vous êtes réel mettant à jour l'auteur. Quelque chose comme:

PUT /authors/{authorId}/updateBookList (et envoyer toute la liste des livres mis à jour dans l'objet auteur)

Je trouve plusieurs erreurs dans mon scénario. Par exemple, envoyer plus de données du client, avoir une certaine logique sur le client, plus de validation sur l'API et aussi compter sur le fait que le client a la dernière version de la liste de livres.

Ma question est la suivante: est-ce anti-pattern pour cela?

SITUATION 1. Dans mon cas, mon API utilise une autre API, pas une base de données. L'API utilisée n'a qu'une seule méthode de "updateBookList", donc je suppose qu'il est plus facile de dupliquer ce comportement dans mon API aussi. Est-ce aussi correct?

SITUATION 2. Mais, en supposant que mon API utilise une base de données, serait-il plus approprié d'utiliser SOLUTION 1?

Aussi, si vous pouviez fournir quelques articles, livres où vous pouvez trouver des informations similaires. Je sais que ce type de conception n'est pas écrit dans la pierre, mais certaines lignes directrices aideraient. (Exemple: REST API Design Rulebook)

+0

Si c'est un vrai problème et non des devoirs, gardez à l'esprit que les livres peuvent avoir plusieurs auteurs. Un livre devrait vraiment être une ressource de premier niveau. –

+0

C'est un vrai problème, mais dans ma situation, la liste des livres appartient à un seul auteur. Par exemple, si vous supprimez un auteur, ces livres n'existeront plus. – green

+0

Pour l'instant. Vous risquez une rupture de l'API si les exigences métier changent. Vous seul pouvez savoir quelle est la probabilité, bien sûr. –

Répondre

2

Je voudrais aller avec la première option et avoir des méthodes distinctes au lieu de bachoter toute la logique à l'intérieur d'un générique PUT. Même si vous utilisez une API au lieu d'une base de données, il s'agit simplement d'une dépendance tierce que vous devriez être en mesure de changer à tout moment, sans avoir à refactoriser trop de votre code.

Cela dit, si vous allez permettre la mise à jour d'un grand nombre de livres à la fois, alors PATCH pourrait être votre ami:

En regardant le RFC 6902 (qui définit la norme de Patch), de point de vue du client l'API pourrait être appelé comme

PATCH /authors/{authorId}/book 
[ 
    { "op": "add", "path": "/ids", "value": [ "24", "27", "35" ]}, 
    { "op": "remove", "path": "/ids", "value": [ "20", "30" ]} 
] 
2

Solution 2 ressemble beaucoup à l'ancienne RPC où une méthode est appelée qui effectue un traitement. C'est comme un anti-pattern REST car REST se concentre sur les ressources et non sur les méthodes. Les opérations que vous pouvez effectuer sur une ressource sont données par le protocole sous-jacent (HTTP dans votre cas) et donc REST devrait adhérer à la sémantique du protocole sous-jacent (l'une de ses quelques contraintes). En outre, REST ne se soucie pas de la façon dont vous configurez vos URI, donc il n'y a pas d'URL RESTful en réalité. Pour un système automatisé, un URI suivant une certaine structure a exactement la même sémantique qu'une chaîne générée de manière aléatoire agissant comme un URI. C'est nous, les humains, qui mettons du sens dans la chaîne même si une application doit utiliser l'attribut rel qui donne à l'URI un nom logique que l'application peut utiliser. Une application qui s'attend à une certaine composition logique d'une URL est déjà étroitement couplée à l'API et viole donc les principes que REST tente de résoudre, à savoir le découplage des clients des API du serveur. Si vous voulez mettre à jour les (sous) ressources via PUT d'une manière RESTful, vous devez suivre la sémantique de put qui stipule que la charge reçue remplace la charge utile accessible à l'URI donné avant la mise à jour.

La méthode PUT demande que l'état de la ressource cible soit créé ou remplacé à l'état défini par la représentation enfermé dans la charge utile du message de demande.

...

La ressource cible dans une requête POST est destiné à traiter la représentation ci-joint selon la propre sémantique de la ressource, tandis que la représentation enfermée dans une requête PUT est défini comme remplaçant l'état de la ressource cible. Par conséquent, l'intention de PUT est idempotente et visible pour les intermédiaires, même si l'effet exact n'est connu que par le serveur d'origine.

En ce qui concerne les mises à jour partielles RFC 7231 indique que des mises à jour partielles sont possibles soit en utilisant PATCH comme suggéré par @Alexandru ou en émettant une demande PUT directement à une sous-ressource où la charge utile remplace le contenu de la sous-ressource avec celui dans la charge utile. Pour la ressource contenant la sous-ressource, cela a un effet sur une mise à jour partielle.

mises à jour de contenu partiels sont possibles par ciblant une ressource identifiée séparément avec l'état qui chevauche une partie de la ressource plus importante, ou en utilisant une autre méthode que a été défini spécifiquement pour les mises à jour partielles (par exemple, la Méthode PATCH définie dans [RFC5789]).

Dans votre cas, vous pouvez donc envoyer la collection de livres mis à jour directement via une opération PUT à quelque chose comme une ressource .../author/{authorId}/books qui remplace l'ancienne collection. Comme cela pourrait ne pas bien évoluer pour les auteurs qui ont écrit de nombreuses publications PATCH est probablement préférable. Notez, cependant, que PATCH nécessite un comportement atomique et transactionnel. Soit toutes les actions réussissent ou pas. Si une erreur survient au milieu des actions, vous devez réintégrer toutes les étapes déjà exécutées. En ce qui concerne votre demande de littérature supplémentaire, SO n'est pas le bon endroit pour poser cette question, car il existe une raison de fermeture/drapeau hors-sujet pour cela.