web-dev-qa-db-fra.com

REST API PATCH ou PUT

Je souhaite concevoir mon noeud final de repos avec la méthode appropriée pour le scénario suivant.

Il y a un groupe. Chaque groupe a un statut. Le groupe peut être activé ou désactivé par l'administrateur.

Dois-je concevoir mon point final comme 

PUT /groups/api/v1/groups/{group id}/status/activate

OR

PATCH /groups/api/v1/groups/{group id}

with request body like 
{action:activate|deactivate}
225
java_geek

La méthode PATCH est le bon choix ici lorsque vous mettez à jour une ressource existante - l'ID de groupe. PUT ne devrait être utilisé que si vous remplacez une ressource dans son intégralité. 

Des informations complémentaires sur la modification partielle des ressources sont disponibles dans RFC 5789 . Plus précisément, la méthode PUT est décrite comme suit:

Plusieurs applications étendant le protocole de transfert hypertexte (HTTP) nécessite une fonctionnalité pour effectuer une modification partielle des ressources. Le La méthode HTTP PUT existante permet uniquement le remplacement complet d'un document. Cette proposition ajoute une nouvelle méthode HTTP, PATCH, pour modifier un fichier ressource HTTP existante.

276
Luke Peterson

Le R dans REST signifie ressource

(Ce qui n’est pas vrai, car il s’agit de Représentation, mais c’est une bonne astuce de rappeler l’importance des ressources dans REST).

À propos de PUT /groups/api/v1/groups/{group id}/status/activate: vous êtes pas en train de mettre à jour un "activer". Un "activer" n'est pas une chose, c'est un verbe. Les verbes ne sont jamais de bonnes ressources. Une règle de base: si l'action, un verbe, est dans l'URL, ce n'est probablement pas RESTful .

Que fais-tu à la place? Soit vous "ajoutez", "supprimez" ou "mettez à jour" un activation sur un groupe, ou si vous préférez: manipuler une ressource "status" sur un groupe. Personnellement, j'utiliserais des "activations" car elles sont moins ambiguës que le concept "statut": créer un statut est ambigu, créer une activation ne l'est pas.

  • POST /groups/{group id}/activation Crée (ou demande la création de) une activation.
  • PATCH /groups/{group id}/activation Met à jour certains détails d'une activation existante. Comme un groupe n'a qu'une seule activation, nous savons à quelle ressource d'activation nous faisons référence.
  • PUT /groups/{group id}/activation insère-ou-remplace l'ancienne activation. Comme un groupe n'a qu'une seule activation, nous savons à quelle ressource d'activation nous faisons référence.
  • DELETE /groups/{group id}/activation Annulera ou supprimera l'activation.

Ce modèle est utile lorsque "l'activation" d'un groupe a des effets secondaires, tels que des paiements en cours, des courriers envoyés, etc. Seuls POST et PATCH peuvent avoir de tels effets secondaires. Quand par exemple par exemple, la suppression d'une activation doit notifier les utilisateurs par courrier électronique, DELETE n'est pas le bon choix; dans ce cas, vous souhaiterez probablement créer une ressource de désactivation: POST /groups/{group_id}/deactivation

Il est judicieux de suivre ces instructions, car ce contrat standard explique très clairement pour vos clients, ainsi que pour tous les serveurs mandataires et toutes les couches qui le séparent, lorsque vous pouvez réessayer en toute sécurité ou non. Supposons que le client utilise une connexion Wi-Fi instable et que son utilisateur clique sur "désactivé", ce qui déclenche un DELETE: si cela échoue, le client peut simplement essayer à nouveau, jusqu'à ce qu'il obtienne un 404, 200 ou tout autre élément qu'il peut gérer. Mais s'il déclenche un POST to deactivation, il ne doit pas réessayer: le POST implique cela.
Tout client a maintenant un contrat qui, s’il est respecté, protégera contre l’envoi de 42 courriels "votre groupe a été désactivé", tout simplement parce que sa bibliothèque HTTP continuait à réessayer l’appel au backend.

Mise à jour d'un seul attribut: utilisez PATCH

PATCH /groups/{group id}

Si vous souhaitez mettre à jour un attribut. Par exemple. le "statut" pourrait être un attribut sur les groupes pouvant être définis. Un attribut tel que "statut" est souvent un bon candidat pour se limiter à une liste blanche de valeurs. Les exemples utilisent un schéma JSON non défini:

PATCH /groups/{group id} { "attributes": { "status": "active" } }
response: 200 OK

PATCH /groups/{group id} { "attributes": { "status": "deleted" } }
response: 406 Not Acceptable

Remplacement de la ressource sans effets secondaires, utilisez PUT.

PUT /groups/{group id}

Si vous souhaitez remplacer un groupe entier. Cela ne signifie pas nécessairement que le serveur crée réellement un nouveau groupe et jette l'ancien, par ex. les identifiants peuvent rester les mêmes. Mais pour les clients, voici ce que PUT can signifie: le client doit supposer qu’il obtient un tout nouvel élément, en fonction de la réponse du serveur.

Dans le cas d'une requête PUT, le client doit toujours envoyer la totalité de la ressource, en disposant de toutes les données nécessaires à la création d'un nouvel élément: généralement les mêmes données que celles requises par une création POST.

PUT /groups/{group id} { "attributes": { "status": "active" } }
response: 406 Not Acceptable

PUT /groups/{group id} { "attributes": { "name": .... etc. "status": "active" } }
response: 201 Created or 200 OK, depending on whether we made a new one.

Une exigence très importante est que PUT soit idempotent: si vous avez besoin d'effets secondaires lors de la mise à jour d'un groupe (ou de la modification d'une activation), vous devez utiliser PATCH. Ainsi, lorsque la mise à jour génère, par exemple, l'envoi d'un courrier, n'utilisez pas PUT.

148
berkes

Je recommanderais d'utiliser PATCH, car votre ressource 'groupe' a de nombreuses propriétés, mais dans ce cas, vous ne mettez à jour que le champ d'activation (modification partielle).

selon la RFC5789 ( https://tools.ietf.org/html/rfc5789 )

La méthode HTTP PUT existante permet uniquement le remplacement complet de un document. Cette proposition ajoute une nouvelle méthode HTTP, PATCH, pour modifier une ressource HTTP existante.

Aussi, plus en détail,

La différence entre les requêtes PUT et PATCH est reflétée dans le fichier façon dont le serveur traite l'entité incluse pour modifier la ressource
identifié par l'URI de la demande. Dans une requête PUT, l'entité incluse est considérée comme une version modifiée de la ressource stockée sur le
Serveur d'origine et le client demande que la version stockée
Est remis, remplacé. Avec PATCH, cependant, l'entité incluse contient un ensemble d'instructions décrivant comment une ressource résidant actuellement sur le
Le serveur d'origine doit être modifié pour produire une nouvelle version. Le patch Cette méthode affecte la ressource identifiée par l'URI de demande et
PEUT aussi avoir des effets secondaires sur d'autres ressources; c'est-à-dire de nouvelles ressources
peuvent être créés ou ceux existants modifiés par l'application d'un
PIÈCE.

PATCH n'est ni sûr ni idempotent tel que défini par [RFC2616], Section 9.1.

Les clients doivent choisir quand utiliser PATCH plutôt que PUT. Pour
Par exemple, si la taille du document du correctif est supérieure à celle du
nouvelles données de ressources qui seraient utilisées dans un PUT, alors cela pourrait rendre
sens d'utiliser PUT au lieu de PATCH. Une comparaison avec POST est encore plus difficile, car POST est utilisé de manières très diverses et peut
englobe les opérations de type PUT et PATCH si le serveur le choisit. Si
l'opération ne modifie pas la ressource identifiée par Request- L'URI de manière prévisible, POST doit être considéré à la place de PATCH
ou PUT.

Le code de réponse pour PATCH est

Le code de réponse 204 est utilisé car la réponse ne porte pas un corps du message (qu’aurait une réponse avec le code 200). Remarque d’autres codes de réussite pourraient également être utilisés.

reportez-vous également à http: //restcookbook.com/HTTP%20Methods/patch/

Avertissement: une API implémentant PATCH doit appliquer un patch de manière atomique. Il ne doit pas Il est possible que les ressources soient à moitié corrigées à la demande d'un GET.

11
Clojurevangelist

Puisque vous voulez concevoir une API en utilisant le style architectural REST, vous devez réfléchir à vos cas d'utilisation pour déterminer les concepts suffisamment importants pour pouvoir être exposés en tant que ressources. Si vous décidez d'exposer le statut d'un groupe en tant que sous-ressource, vous pouvez lui attribuer l'URI suivant et implémenter la prise en charge des méthodes GET et PUT: 

/groups/api/groups/{group id}/status

L'inconvénient de cette approche par-dessus le PATCH pour modification est que vous ne pourrez pas modifier plus d'une propriété d'un groupe de manière atomique et transactionnelle. Si les modifications transactionnelles sont importantes, utilisez PATCH.

Si vous décidez d'exposer le statut en tant que sous-ressource d'un groupe, il doit s'agir d'un lien dans la représentation du groupe. Par exemple, si l'agent obtient le groupe 123 et accepte XML, le corps de la réponse peut contenir: 

<group id="123">
  <status>Active</status>
  <link rel="/linkrels/groups/status" uri="/groups/api/groups/123/status"/>
  ...
</group>

Un hyperlien est nécessaire pour remplir l'hypermédia en tant que moteur de l'état de l'application condition du style architectural REST.

7
Andrew Dobrowolski

Je préférerais généralement quelque chose d'un peu plus simple, comme une sous-ressource activate/deactivate (liée par un en-tête Link avec rel=service).

POST /groups/api/v1/groups/{group id}/activate

ou

POST /groups/api/v1/groups/{group id}/deactivate

Pour le consommateur, cette interface est extrêmement simple et suit les principes de REST sans vous embrouiller dans la conceptualisation des "activations" en tant que ressources individuelles.

0
rich remer