web-dev-qa-db-fra.com

Pourquoi HTTP PUT n'est-il pas autorisé à effectuer des mises à jour partielles dans une API REST?

Qui a dit que les API RESTful doivent prendre en charge les mises à jour partielles séparément via HTTP PATCH?

Il semble n'avoir aucun avantage. Cela ajoute plus de travail à implémenter côté serveur et plus de logique côté client pour décider du type de mise à jour à demander.

Je pose cette question dans le contexte de la création d'une API REST avec HTTP qui fournit l'abstraction aux modèles de données connus. Exiger PATCH pour les mises à jour partielles par opposition à PUT pour les mises à jour complètes ou partielles donne l'impression qu'il n'a pas bénéficier, mais je pourrais être convaincu.

Connexes

http://restcookbook.com/HTTP%20Methods/idempotency/ - cela implique que vous n'avez pas le contrôle sur le logiciel serveur qui peut mettre en cache les demandes.

Quelle est la justification derrière le refus de PUT partiel? - aucune réponse claire donnée, seule référence à ce que HTTP définit pour PUt vs PATCH.

http://groups.yahoo.com/neo/groups/rest-discuss/conversations/topics/17415 - montre la division des opinions à ce sujet.

36
Brenden

Qui dit? Le gars qui a inventé REST dit:

@mnot Oy, oui, PATCH a été quelque chose que j'ai créé pour la proposition HTTP/1.1 initiale car le PUT partiel n'est jamais RESTful. ;-)

https://Twitter.com/fielding/status/275471320685367296

Tout d'abord, REST est un style architectural, et l'un de ses principes est de tirer parti du comportement normalisé du protocole sous-jacent, donc si vous voulez implémenter une API RESTful sur HTTP, vous devez suivre HTTP strictement pour qu'il soit RESTful. Vous êtes libre de ne pas le faire si vous pensez que ce n'est pas suffisant pour vos besoins, personne ne vous maudira pour cela, mais alors vous ne faites pas REST. Vous devrez documenter où et comment vous vous écartez de la norme, créant un couplage solide entre les implémentations client et serveur, et l'intérêt d'utiliser REST est précisément d'éviter cela et de vous concentrer sur vos types de médias.

Ainsi, sur la base de la RFC 7231, PUT ne doit être utilisé que pour le remplacement complet d'une représentation, dans une opération idempotente. PATCH devrait être utilisé pour les mises à jour partielles, qui ne doivent pas nécessairement être idempotentes, mais il est bon de les rendre idempotentes en exigeant une condition préalable ou en validant l'état actuel avant d'appliquer la différence. Si vous devez effectuer des mises à jour non idempotentes, partielles ou non, utilisez POST. Facile. Tous ceux qui utilisent votre API et qui savent comment fonctionnent PUT et PATCH s'attendent à ce qu'ils fonctionnent de cette manière, et vous n'avez pas à documenter ni à expliquer ce que les méthodes doivent faire pour une ressource donnée. Vous êtes libre de faire agir PUT de toute autre manière que vous jugez appropriée, mais vous devrez ensuite documenter cela pour vos clients et vous devrez trouver un autre mot à la mode pour votre API, car ce n'est pas RESTful.

Gardez à l'esprit que REST est un style architectural axé sur l'évolution à long terme de votre API. Pour le faire correctement , il faudra ajoutez plus de travail maintenant, mais cela rendra les modifications plus faciles et moins traumatisantes plus tard. Cela ne signifie pas REST convient à tout et à tous. Si votre objectif est la facilité de mise en œuvre et d'utilisation à court terme, utilisez simplement les méthodes comme vous le souhaitez. Vous pouvez tout faire par le biais de POST si vous ne voulez pas vous soucier des clients qui choisissent les bonnes méthodes.

53
Pedro Werneck

Pour étendre sur la réponse existante , PUT est censé effectuer une mise à jour complète (écraser) de l'état de la ressource simplement parce que HTTP définit la méthode de cette manière. RFC 2616 original sur HTTP/1.1 n'est pas très explicite à ce sujet, RFC 7231 ajoute des clarifications sémantiques:

4.3.4 PUT

La méthode PUT demande que l'état de la ressource cible soit créé ou remplacé par l'état défini par la représentation incluse dans la charge utile du message de demande. Un PUT réussi d'une représentation donnée suggère qu'un GET ultérieur sur cette même ressource cible entraînera l'envoi d'une représentation équivalente dans une réponse 200 (OK).

Comme indiqué dans l'autre réponse, le respect de cette convention simplifie la compréhension et l'utilisation des API, et il n'est pas nécessaire de documenter explicitement le comportement de la méthode PUT.


Cependant, les mises à jour partielles ne sont pas interdites en raison de l'idempotence. Je trouve cela important à souligner, car ces concepts sont souvent confondus, même sur de nombreuses réponses StackOverflow (par exemple ici ).

Idempotent signifie uniquement que l'application une ou plusieurs fois d'une requête entraîne le même effet sur le serveur. Pour citer à nouveau la RFC 7231:

4.2.2 Méthodes idempotentes

Une méthode de requête est considérée comme "idempotente" si l'effet prévu sur le serveur de plusieurs requêtes identiques avec cette méthode est le même que l'effet pour une seule requête de ce type.

Tant qu'une mise à jour partielle ne contient que de nouvelles valeurs de l'état de la ressource et ne dépend pas des valeurs précédentes (c'est-à-dire que ces valeurs sont remplacées), l'exigence d'idempotency est remplie. Indépendamment du nombre de fois où une telle mise à jour partielle est appliquée, l'état du serveur contiendra toujours les valeurs spécifiées dans la demande.

La question de savoir si une demande intermédiaire d'un autre client peut modifier une autre partie de la ressource n'est pas pertinente, car l'idempotence fait référence à la opération (c'est-à-dire la méthode PUT), pas à l'état lui-même . Et en ce qui concerne le fonctionnement d'une mise à jour de remplacement partiel, son application produit le même effet après avoir été appliquée une ou plusieurs fois.

Au contraire, une opération qui n'est pas idempotente dépend de l'état actuel du serveur, donc elle conduit à des résultats différents selon le nombre de fois où elle est exécutée. L'exemple le plus simple consiste à incrémenter un nombre (non idempotent) par rapport à sa valeur absolue (idempotent).

Pour les modifications non idempotentes, HTTP prévoit les méthodes POST et PATCH, tandis que PATCH est explicitement conçu pour apporter des modifications à une ressource existante, tandis que POST peut être interprété beaucoup plus librement en ce qui concerne la relation entre l'URI de la demande, le contenu du corps et les effets secondaires sur le serveur.


Qu'est-ce que cela signifie dans la pratique? REST est un paradigme pour implémenter des API sur le protocole HTTP - une convention qui beaucoup de gens ont considéré raisonnable et est donc susceptible d'être adopté ou compris. Pourtant, il y a des controverses concernant ce qui est RESTful et ce qui ne l'est pas, mais même en les laissant de côté, REST n'est pas le seul manière correcte ou significative de créer des API HTTP.

Le protocole HTTP lui-même impose des contraintes sur ce que vous pouvez et ne pouvez pas faire, et beaucoup d'entre eux ont un réel impact pratique. Par exemple, ne pas tenir compte de l'idempotency peut entraîner des serveurs de cache modifiant le nombre de demandes réellement émises par le client et perturber par la suite la logique attendue par les applications. Il est donc crucial d'être conscient des implications lors de la déviation de la norme.

Étant strictement conforme à REST, il n'y a pas de solution complètement satisfaisante pour les mises à jour partielles (certains disent même que ce besoin seul est contre REST). Le problème est que PATCH, qui semble avoir été créé uniquement à cet effet, n'est pas idempotent. Ainsi, en utilisant PATCH pour les mises à jour partielles idempotentes, vous perdez les avantages de l'idempotence (nombre arbitraire de tentatives automatiques, logique plus simple, potentiel pour optimisations client, serveur et réseau). En tant que tel, vous pouvez vous demander si l'utilisation de PUT est vraiment la pire idée, tant que le comportement est clairement documenté et ne se casse pas parce que les utilisateurs (et les nœuds de réseau intermédiaires) dépendent d'un certain comportement ...?

8
TheOperator