web-dev-qa-db-fra.com

Manipulation de collection en masse via une API REST (RESTful)

J'aimerais avoir des conseils sur la conception d'une API REST qui permettra aux clients d'ajouter/supprimer un grand nombre d'objets dans une collection de manière efficace.

Via l'API, les clients doivent pouvoir ajouter des éléments à la collection et en supprimer des éléments, ainsi que manipuler des éléments existants. Dans de nombreux cas, le client voudra effectuer des mises à jour en masse de la collection, par exemple ajouter 1000 éléments et supprimer 500 éléments différents. Il semble que le client devrait être en mesure de le faire en une seule transaction avec le serveur, plutôt que d'exiger 1000 POST requêtes distinctes et 500 DELETEs).

Quelqu'un a-t-il des informations sur les meilleures pratiques ou conventions pour y parvenir?

Ma pensée actuelle est que l'on devrait pouvoir METTRE un objet représentant le changement de l'URI de collection, mais cela semble en contradiction avec le HTTP 1.1 RFC , ce qui semble suggérer que les données envoyées dans un PUT la demande doit être interprétée indépendamment des données déjà présentes à l'URI. Cela implique que le client devrait envoyer une description complète du nouvel état de la collection en une seule fois, ce qui pourrait bien être beaucoup plus important que le changement, ou même être plus que ce que le client sait lorsqu'il fait la demande.

Évidemment, je serais heureux de déroger à la RFC si nécessaire, mais je préférerais le faire de manière conventionnelle si une telle convention existe.

71
mattwynne

Vous voudrez peut-être considérer la tâche de changement comme une ressource en soi. Vous êtes donc vraiment en train de mettre un seul objet, qui est un objet de mise à jour en masse des données. Peut-être qu'il a un nom, un propriétaire et une grosse tache de CSV, XML, etc. qui doit être analysé et exécuté. Dans le cas de CSV, vous souhaiterez peut-être également identifier le type d'objets représentés dans les données CSV.

Lister les travaux, ajouter un travail, afficher l'état d'un travail, mettre à jour un travail (probablement pour le démarrer/l'arrêter), supprimer un travail (l'arrêter s'il est en cours d'exécution), etc. Ces opérations sont facilement mappées sur un REST.

Une fois que vous avez cela en place, vous pouvez facilement ajouter différents types de données que votre programme de mise à jour de données en bloc peut gérer, peut-être même mélangés ensemble dans la même tâche. Il n'est pas nécessaire d'avoir cette même API dupliquée partout dans votre application pour chaque type de chose que vous souhaitez importer, en d'autres termes.

Cela se prête également très facilement à une implémentation en tâche de fond. Dans ce cas, vous souhaiterez probablement ajouter des champs aux objets de tâche individuels qui permettent au client API de spécifier comment ils veulent être notifiés (une URL qu'ils souhaitent que vous OBTENEZ quand c'est fait, ou leur envoyer un e-mail, etc.) .

62
Jamie Flournoy

Oui, PUT crée/écrase, mais ne met pas à jour partiellement.

Si vous avez besoin d'une sémantique de mise à jour partielle, utilisez PATCH. Voir http://greenbytes.de/tech/webdav/draft-dusseault-http-patch-14.html .

9
Julian Reschke

Vous devez utiliser AtomPub . Il est spécialement conçu pour gérer les collections via HTTP. Il pourrait même y avoir une implémentation pour la langue de votre choix.

2
dowski

Pour les POST, au moins, il semble que vous devriez être en mesure de POST vers une URL de liste et que le corps de la demande contienne une liste de nouvelles ressources au lieu d'une seule nouvelle ressource.

2
Hank Gay

Pour autant que je le comprends, REST signifie transfert d'état représentatif, vous devez donc transférer l'état du client vers le serveur.

Si cela signifie que trop de données vont et viennent, vous devrez peut-être modifier votre représentation. Une structure collectionChange fonctionnerait, avec une série de suppressions (par id) et d'ajouts (avec des représentations xml complètes intégrées), POSTed à une URL d'interface de gestion. L'implémentation de l'interface peut choisir sa propre méthode pour les suppressions et les ajouts côté serveur.

La version la plus pure serait probablement de définir les éléments par URL, et la collection contient une série d'URL. La nouvelle collection peut être PUT après modifications par le client, suivie d'une série de PUT des éléments ajoutés, et peut-être d'une série de suppressions si vous souhaitez réellement supprimer les éléments du serveur plutôt que de simplement les supprimer de cette liste.

1
Phil H

Vous pouvez introduire une méta-représentation des éléments de collection existants qui n'ont pas besoin que leur état entier soit transféré, donc dans un code abstrait, votre mise à jour pourrait ressembler à ceci:

{éléments existants 1-100} 
 {nouvel élément foo avec les valeurs "bar", "baz"} 
 {élément existant 105} 
 {nouvel élément foobar avec les valeurs "bar" , "foo"} 
 {éléments existants 110-200}

L'ajout (et la modification) d'éléments se fait en définissant leurs valeurs, la suppression d'éléments se fait en ne le mentionnant pas la nouvelle collection et la réorganisation des éléments se fait en spécifiant la nouvelle commande (si la commande est stockée).

De cette façon, vous pouvez facilement représenter la nouvelle collection entière sans avoir à retransmettre tout le contenu. Utilisant un If-Unmodified-Since header garantit que votre idée du contenu correspond bien à celle des serveurs (afin de ne pas supprimer accidentellement des éléments que vous ne saviez tout simplement pas au moment où la demande a été soumise).

0
Joachim Sauer