web-dev-qa-db-fra.com

Pourquoi PATCH n'est ni sûr ni idempotent?

J'ai du mal à comprendre pourquoi PATCH n'est pas sûr où se trouve PUT. De même, la partie idempotente - si je mets à jour un champ de la ressource, ce champ ne retournerait-il pas la même valeur après la mise à jour?

17
Tony Vincent

Tout d'abord, PUT n'est pas non plus sûr.

Les méthodes sûres sont des méthodes HTTP qui ne modifient pas les ressources. Par exemple, utiliser GET ou HEAD sur une URL de ressource, ne doit JAMAIS changer la ressource.

Puisque PUT request (tout comme PATCH d'ailleurs) met à jour la ressource, donc elle ne peut pas être mise en cache et donc elle n'est pas SÉCURITAIRE.

PUT la demande est idempotente, ou je devrais dire PUT la demande doit être idempotente.

Une méthode HTTP idempotente est une méthode HTTP qui peut être appelée plusieurs fois sans résultats différents. Peu importe que la méthode soit appelée une seule fois ou dix fois. Le résultat devrait être le même. Encore une fois, cela ne s'applique qu'au résultat, pas à la ressource elle-même. Cela peut toujours être manipulé (comme un horodatage de mise à jour, à condition que ces informations ne soient pas partagées dans la représentation des ressources (actuelle).

L'idée derrière la demande de PUT étant idempotente est que si un appel de mise à jour sur une ressource échoue, un client peut refaire le même appel sans provoquer aucun état indésirable ou incohérent. La demande PUT doit toujours être précédée d'une demande GET à la ressource et doit réussir si et si seule la ressource n'a pas changé depuis. Pour l'élaboration: - passez par l'une des réponses similaires - requête PUT idempotente dans un environnement simultané

Maintenant, la requête PATCH est destinée à mettre à jour uniquement les champs sélectifs, elle ne devrait PAS OBTENIR la représentation des ressources. Ainsi, plusieurs appels à la requête PATCH pourraient se traduire par un changement indésirable de l'état des ressources. Ce n'est donc pas IDEMPOTENT.

Par exemple: - Il existe une ressource Person

Requête 1: PATCH/person/1 {'age': 10} - met à jour l'âge de la ressource à 10

Supposons maintenant qu'une autre demande parallèle modifie l'état de la ressource, par exemple

Requête 2: PATCH/person/1 {'age': 19} - met à jour l'âge de la ressource à 19

Maintenant, si envoie à nouveau la demande 1, il mettra à nouveau l'âge de la ressource à 10, provoquant ainsi un résultat indésirable.

Il peut être rendu idempotent en utilisant des en-têtes etags ou If Modified Since.

1
hspandher

Ce n'est pas sûr car en général, vous ne pouvez pas exécuter en toute sécurité une demande PATCH sans changer de ressource (c'est à cela qu'il sert).

Alors pourquoi PATCH n'est-il pas idempotent par rapport à PUT? C'est parce que la façon dont vous appliquez vos modifications est importante. Si vous souhaitez modifier la propriété name d'une ressource, vous pouvez envoyer quelque chose comme {"name": "foo"} en tant que charge utile et qui serait en effet idempotent puisque l'exécution de cette requête autant de fois que cela donnerait le même résultat: l'attribut resources name est maintenant "foo".

Mais PATCH est beaucoup plus général dans la façon dont vous pouvez changer une ressource (vérifiez la définition this sur la façon d'appliquer un patch JSON). Cela pourrait également, par exemple, signifier déplacer la ressource et ressembler à ceci: { "op": "move", "from": "/a/b/c", "path": "/a/b/d" }. Cette opération n'est évidemment pas idempotente car un deuxième appel entraînerait une erreur.

Ainsi, alors que la plupart des opérations PATCH peuvent être idempotentes, certaines ne le sont pas.

Une remarque sur les autres réponses: l'idempotence est définie en répétant une opération plusieurs fois de suite. Dire que quelque chose n'est pas idempotent parce que l'effet est différent si une autre opération a été exécutée entre ou en parallèle n'est tout simplement pas un argument valide (aucune opération ne serait idempotente en général si c'était le cas). Mathématiquement, une transformation idempotente est celle qui donne le même résultat, quelle que soit la fréquence à laquelle vous l'appliquez (comme faire pivoter quelque chose à 360 degrés). Bien sûr, une rotation de 360 ​​degrés peut donner des résultats différents si vous appliquez une autre opération entre les deux.

18
C. Doe

PATCH modifie les attributs des ressources. Le changement peut nécessiter une valeur précédente concrète de l'attribut, ce qui le rend NON idempotent.

From Name=John to Name=Gargantua. 

Après l'application répétée, le nom sera Gargantua et le patch échouera, car il faut que le nom soit "John" avant le changement

"from Name=John"

5
Skip

J'ai récemment commencé à chercher si Patch est idempotent ou non et après avoir lu sur le format de patch JSON, j'ai compris que si l'opération d'ajout est appliquée en utilisant la méthode Patch, il est tout à fait possible que la demande soit non idempotente car elle pourrait ajouter les nouvelles valeurs à une ressource existante si la même demande est effectuée plusieurs fois.

{"op": "add", "path": "/ a/b/c", "value": ["foo", "bar"]}

4
user1570094