web-dev-qa-db-fra.com

REST: Mise à jour de plusieurs ressources en une seule demande - Est-ce standard ou à éviter?

Une simple REST API:

  • GET: items/{id} - Retourne une description de l'item avec l'id donné
  • PUT: items/{id} - Met à jour ou crée l'élément avec l'identifiant donné
  • DELETE: items/{id} - Supprime l'élément avec l'identifiant donné

Maintenant, l'extension API en question:

  • GET: items? Filter - Renvoie tous les ID d’élément correspondant au filtre.
  • PUT: items - Met à jour ou crée un ensemble d’articles comme décrit par la charge JSON.
  • [[DELETE: items - supprime une liste d'éléments décrits par la charge JSON}]] <- Non correct

Je suis maintenant intéressé par la fonctionnalité de recyclage des opérations DELETE et PUT, facilement accessible avec les éléments PUT/DELETE/{id}. 

Question: Est-il courant de fournir une API comme celle-ci?

Alternative: à l’ère de la connexion unique, les demandes multiples émises par plusieurs sont peu coûteuses et fonctionneraient mieux si un changement réussissait ou échouait, mais à l’ère de la base de données NOSQL, un changement dans la liste pouvait déjà s’être produit même si le traitement de la demande mourait serveur interne ou quoi que ce soit pour une raison quelconque.

[METTRE À JOUR]

Après avoir examiné Normes Web de la Maison Blanche et Wikipedia: REST Exemples l'exemple suivant API est maintenant conçu:

Une simple REST API:

  • GET: items/{id} - Retourne une description de l'item avec l'id donné
  • PUT: items/{id} - Met à jour ou crée l'élément avec l'identifiant donné
  • DELETE: items/{id} - Supprime l'élément avec l'identifiant donné

API top-resource:

  • GET: items? Filter - Renvoie tous les ID d’élément correspondant au filtre.
  • POST: items - Met à jour ou crée un ensemble d’articles comme décrit par la charge JSON.

PUT et DELETE sur/items n'est pas pris en charge et interdit.

Utiliser POST semble être l’astuce, c’est-à-dire créer de nouveaux éléments dans une ressource englobante sans remplacer, mais ajouter.

Sémantique HTTP POST Lit:

Extension d'une base de données via une opération d'ajout

Où les méthodes PUT nécessiteraient de remplacer la collection complète afin de renvoyer une représentation équivalente à celle indiquée par HTTP Semantics PUT :

Une PUT réussie d'une représentation donnée suggérerait qu'une opération GET ultérieure sur la même ressource cible entraînera le renvoi d'une représentation équivalente dans une réponse 200 (OK).

[UPDATE2]

Une méthode qui semble encore plus cohérente pour l'aspect mise à jour de plusieurs objets semble être la méthode PATCH. La différence entre PUT et PATCH est décrite dans le Draft RFC 5789 comme étant:

La différence entre les requêtes PUT et PATCH est reflétée dans la façon dont le serveur traite l'entité incluse pour modifier la ressource identifiée par l'URI de demande. Dans une demande PUT, l'entité incluse est considérée comme une version modifiée de la ressource stockée sur le serveur Origin et le client demande le remplacement de la version stockée. Cependant, avec PATCH, l'entité incluse contient un ensemble d'instructions décrivant la manière dont une ressource résidant actuellement sur le serveur Origin doit être modifiée pour produire une nouvelle version. La méthode PATCH affecte la ressource identifiée par l'URI de demande, et PEUT aussi avoir des effets secondaires sur d'autres ressources; c'est-à-dire que de nouvelles ressources peuvent être créées ou que des ressources existantes peuvent être modifiées par l'application d'un PATCH.

Donc, comparé à POST, PATCH peut aussi être une meilleure idée puisque PATCH permet une MISE À JOUR où POST permet uniquement d’ajouter quelque chose qui signifie ajouter sans possibilité de modification.

Donc POST semble avoir tort et nous devons modifier notre API proposée pour:

Une simple REST API:

  • GET: items/{id} - Retourne une description de l'item avec l'id donné
  • PUT: items/{id} - Met à jour ou crée l'élément avec l'identifiant donné
  • DELETE: items/{id} - Supprime l'élément avec l'identifiant donné

API top-resource:

  • GET: items? Filter - Renvoie tous les ID d’élément correspondant au filtre.
  • POST: items - Crée un ou plusieurs éléments comme décrit par la charge JSON.
  • PATCH: items - Crée ou met à jour un ou plusieurs éléments comme décrit par la charge JSON.
43
Martin Kersten

Vous pouvez PATCH la collection, par exemple 

PATCH /items
[ { id: 1, name: 'foo' }, { id: 2, name: 'bar' } ]

Techniquement, PATCH identifierait l'enregistrement dans l'URL (c'est-à-dire PATCH /items/1 et non dans le corps de la demande, mais cela semble être une bonne solution pragmatique.

Pour prendre en charge la suppression, la création et la mise à jour en un seul appel, ce n'est pas vraiment pris en charge par les conventions standard REST. Une possibilité est un service spécial "batch" qui vous permet d'assembler des appels:

POST /batch
[
  { method: 'POST', path: '/items', body: { title: 'foo' } },
  { method: 'DELETE', path: '/items/bar' }
]

qui renvoie une réponse avec des codes d'état pour chaque demande intégrée:

[ 200, 403 ]

Pas vraiment standard, mais je l’ai fait et ça marche.

35
mahemoff

Autant que je sache, le concept REST couvre la mise à jour de plusieurs ressources avec une seule demande. En réalité, l’astuce consiste à supposer qu’un conteneur est constitué de plusieurs ressources et qu’il est considéré comme une ressource unique. Par exemple. vous pouvez simplement supposer que cette liste d'identifiants identifie une ressource qui contient plusieurs autres ressources.

Dans ces exemples dans Wikipedia , ils parlent également de ressources en pluriel.

1
Kris

Mise à jour de plusieurs ressources en une seule demande - Est-ce standard ou à éviter?

Parfois, vous devez simplement exécuter des opérations de traitement par lots atomiques ou d’autres opérations liées aux ressources qui ne correspondent tout simplement pas au schéma typique d’une API simple REST, mais si vous en avez besoin, vous ne pouvez pas l’éviter.

Est-ce standard?

Il n’existe pas de norme universellement acceptée REST - API. Il est donc difficile de répondre à cette question. Cependant, en consultant certaines instructions de conception API couramment citées, telles que jsonapi.org , restfulapi.net , Guide de conception Microsoft api ou IBM REST Conventions API , qui ne mentionnent pas toutes les opérations par lots, vous pouvez en déduire que ces opérations ne sont généralement pas comprises comme une fonctionnalité standard des REST API.

Cela dit, le guide de conception Google Api constitue une exception. Mentionne la création de méthodes "personnalisées" pouvant être associées via une ressource à l'aide de deux points, par exemple. https://service.name/v1/some/resource/name:customVerb, il mentionne aussi explicitement les opérations par lots comme cas d'utilisation:

Une méthode personnalisée peut être associée à une ressource, une collection ou un service. Il peut prendre une requête arbitraire et renvoyer une réponse arbitraire, et prend également en charge la requête et la réponse en continu. [...] Les méthodes personnalisées doivent utiliser HTTP POST verbe, car il possède la sémantique la plus flexible [...] Pour les méthodes critiques en termes de performances, il peut être utile de fournir des méthodes de traitement par lots personnalisées pour réduire frais généraux de la demande.

Ainsi, dans le cas que vous avez fourni, procédez comme suit, selon le guide des API de Google:

POST /api/items:batchUpdate

En outre, certaines API publiques ont décidé d’offrir un point de terminaison /batch central, par exemple. l'API Gmail de Google .

En outre, comme mentionné sur restfulapi.net, il existe également le concept de ressource "magasin", dans lequel vous stockez et récupérez des listes entières d'éléments à la fois via PUT - toutefois, ce concept ne compte pas pour serveur - collections de ressources gérées:

Un magasin est un référentiel de ressources géré par le client. Une ressource de magasin permet à un client d'API de placer des ressources, de les récupérer et de décider quand les supprimer. Un magasin ne génère jamais de nouveaux URI. Au lieu de cela, chaque ressource stockée a un URI qui a été choisi par un client lorsqu’elle a été initialement placée dans le magasin.


Après avoir répondu à vos questions initiales, voici une autre approche de votre problème qui n’a pas encore été mentionnée. Veuillez noter que cette approche est un peu non conventionnelle et ne semble pas aussi jolie que le schéma de nommage de noeud final typique REST API. Personnellement, je ne suis pas cette approche, mais j’ai toujours pensé qu’il fallait y penser :)

L'idée est que vous pouvez faire une distinction entre les opérations CRUD sur une ressource et les autres opérations associées aux ressources (par exemple, les opérations par lots) via votre schéma de dénomination de chemin d'accès au noeud final.

Par exemple, considérons une API RESTful qui vous permet d'effectuer des opérations CRUD sur une ressource "société" et vous souhaitez également effectuer certaines opérations liées à la "société" qui ne s'inscrivent pas dans le schéma CRUD axé sur les ressources généralement associé aux API reposantes - tels que les opérations par lots que vous avez mentionnées.

Maintenant, au lieu d'exposer vos ressources directement sous /api/companies (par exemple /api/companies/22), vous pouvez distinguer:

  • /api/companies/items - c’est-à-dire un ensemble de ressources de la société
  • /api/companies/ops - c.-à-d. opérations liées aux ressources de l'entreprise

Pour items, les méthodes http habituelles de l’API RESTful et les schémas de nommage des ressources (URL) s’appliquent (par exemple, comme indiqué ici ou ici ).

POST    /api/companies/items
GET     /api/companies/items
GET     /api/companies/items/{id}
DELETE  /api/companies/items/{id}
PUT     /api/companies/items/{id}

Désormais, pour les opérations liées à la société, vous pouvez utiliser le préfixe de route /api/companies/ops/ et appeler des opérations via POST.

POST    /api/companies/ops/batch-update
POST    /api/companies/ops/batch-delete
POST    /api/companies/ops/garbage-collect-old-companies
POST    /api/companies/ops/increase-some-timestamps-just-for-fun
POST    /api/companies/ops/perform-some-other-action-on-companies-collection

Depuis POST les requêtes ne doivent pas nécessairement aboutir à la création d'une ressource, POST est la bonne méthode à utiliser ici:

L'action effectuée par la méthode POST peut ne pas aboutir à une ressource pouvant être identifiée par un URI . https://tools.ietf.org/html/rfc2616#section-9.5

1
B12Toaster