216 votes

Meilleure pratique pour les mises à jour partielles dans un service RESTful

Je suis en train d'écrire un service RESTful pour un système de gestion des clients et je suis en train d'essayer de trouver la meilleure pratique pour la mise à jour des enregistrements partiellement. Par exemple, je veux de l'appelant afin d'être en mesure de lire l'intégralité de l'enregistrement avec une requête GET. Mais pour la mise à jour de ce que certaines des opérations sur le document sont autorisées, comme le changement de statut de enabled (ACTIVÉ) disabled (DÉSACTIVÉ). (J'ai des scénarios plus complexes que cela)

Je ne veux pas l'appelant de présenter la totalité de l'enregistrement avec juste la mise à jour de champ pour des raisons de sécurité (il se sent aussi comme overkill).

Est-il recommandé manière de construire les URIs? Lors de la lecture du RESTE des livres de type RPC appels semblent être mal vu.

Si l'appel suivant retourne la totalité du dossier client pour le client avec l'id 123

GET /customer/123
<customer>
    {lots of attributes}
    <status>ENABLED</status>
    {even more attributes}
</customer>

comment dois-je mettre à jour l'état?

POST /customer/123/status
<status>DISABLED</status>

POST /customer/123/changeStatus
DISABLED

...

Mise à jour: Pour compléter la question. Comment intégrer des " logique commerciale d'appels dans une api REST? Est-il convenu de la manière de procéder? Pas tous les moyens sont CRUD par la nature. Certains sont plus complexes, comme"sendEmailToCustomer(123)', 'mergeCustomers(123, 456)', 'countCustomers()'

POST /customer/123?cmd=sendEmail

POST /cmd/sendEmail?customerId=123

GET /customer/count 

Merci Frank

71voto

Jan Algermissen Points 2915

En gros, vous avez deux options:

  1. L'utilisation du PATCH (mais notez que vous avez défini vous propre type de média qui spécifie ce qui va se passer exactement)

  2. Utilisation POST à un sous de ressources et de retour 303 Voir d'Autres avec l'Emplacement de l'en-tête pointant vers la ressource principale. L'intention de l'303 est-à-dire au client: "j'ai accompli de votre POST, et l'effet a été que certains autres ressources a été mis à jour. Voir l'en-tête location pour lesquels la ressource." POST/303 est prévu pour itératif ajouts de ressources pour construire l'etat de certaines principale ressource et il est un ajustement parfait pour des mises à jour partielles.

Jan

52voto

wsorenson Points 2364

Vous devez utiliser des POST pour les mises à jour partielles.

Pour mettre à jour les champs pour le client 123, faire un POST à /client/123.

Si vous souhaitez uniquement mettre à jour le statut, vous pouvez également METTRE à /client/123/statut.

En général, les requêtes GET ne devrait pas avoir d'effets secondaires, et la METTRE pour l'écriture/le remplacement de la totalité de la ressource.

Cela résulte directement à partir de l'adresse HTTP, comme on le voit ici: http://en.wikipedia.org/wiki/HTTP_PUT#Request_methods

12voto

Jørn Wildt Points 828

Vous devez utiliser le PATCH pour les mises à jour partielles - soit en utilisant json-patch documents (voir http://tools.ietf.org/html/draft-ietf-appsawg-json-patch-08 ou http://www.mnot.net/blog/2012/09/05/patch) ou le XML patch cadre (voir http://tools.ietf.org/html/rfc5261). À mon avis cependant, json-patch est le mieux adapté à votre type de données de l'entreprise.

PATCH avec JSON/XML patch documents a très détroit vers l'avant de la sémantique pour des mises à jour partielles. Si vous commencez à l'aide de POST, avec les copies modifiées du document original, pour des mises à jour partielles bientôt vous rencontrer des problèmes lorsque vous souhaitez valeurs manquantes (ou, plutôt, les valeurs nulles) pour représenter "ignorer cette propriété" ou "définir cette propriété sur la valeur vide" - et qui mène vers le bas un trou de lapin de piraté des solutions qui en fin de compte, votre propre type de format de patch.

Vous pouvez trouver un plus en profondeur de réponse ici: http://soabits.blogspot.dk/2013/01/http-put-patch-or-post-partial-updates.html.

8voto

user360657 Points 31

Je suis confronté à un problème similaire. METTRE sur un sous-ressource semble fonctionner lorsque vous souhaitez mettre à jour un champ unique. Cependant, parfois, vous souhaitez mettre à jour un tas de choses: Pensez à un formulaire web qui représente la ressource avec la possibilité de changer certaines entrées. L'utilisateur de la soumission de formulaire ne doit pas entraîner une plusieurs place.

Voici deux solutions que je peux penser:

  1. faire un avec la totalité de la ressource. Sur le côté serveur, définir la sémantique qu'un avec la totalité de la ressource ignore toutes les valeurs qui n'ont pas changé.

  2. faire un PUT avec un partiel de ressources. Sur le côté serveur, définir la sémantique de ce la fusion.

2 est juste une bande passante-optimisation des 1. Parfois 1 est la seule option si la ressource définit certains champs sont des champs obligatoires (pensez proto tampons).

Le problème avec ces deux approches est de savoir comment effacer un champ. Vous devrez définir un spécial valeur null (en particulier pour les proto tampons depuis les valeurs null ne sont pas définies pour les proto tampons) qui sera la cause de la compensation du champ.

Des commentaires?

5voto

manuel aldana Points 4317

Choses à ajouter à votre augmentée question. Je pense que vous pouvez souvent parfaitement conception plus complexe des affaires d'actions. Mais vous avez à donner la méthode/procédure de style de pensée et de penser davantage en termes de ressources et de verbes.

mail envois


POST /customers/123/mails

payload:
{from: x@x.com, subject: "foo", to: y@y.com}

La mise en œuvre de cette ressource + POST serait alors envoyer le mail. si nécessaire, vous pouvez offrir quelque chose comme /client/123/boîte d'envoi, puis offrir des liens vers les ressources de /le client/mails/{mailId}.

comptage des clients

Vous pourriez traiter comme une ressource de recherche (y compris les métadonnées de recherche avec la pagination et num trouvé d'informations, ce qui vous donne le nombre de clients).


GET /customers

response payload:
{numFound: 1234, paging: {self:..., next:..., previous:...} customer: { ...} ....}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X