Existe-t-il des problèmes avec la mise en œuvre de méthodes HTTP personnalisées?

34

Nous avons une URL au format suivant

/ instance / {instanceType} / {instanceId}

Vous pouvez l'appeler avec les méthodes HTTP standard: POST, GET, DELETE, PUT. Cependant, il y a quelques actions supplémentaires que nous prenons comme "Enregistrer comme brouillon" ou "Curate"

Nous pensions pouvoir utiliser des méthodes HTTP personnalisées telles que: DRAFT, VALIDATE, CURATE

Je pense que cela est acceptable puisque les normes disent

"L'ensemble des méthodes courantes pour HTTP / 1.1 est défini ci-dessous. Bien que cet ensemble puisse être développé, des méthodes supplémentaires ne peuvent pas être supposées partager la même sémantique pour des clients et des serveurs étendus séparément."

Et des outils tels que WebDav créent certaines de leurs propres extensions.

Existe-t-il des problèmes rencontrés par certaines méthodes personnalisées? Je pense aux serveurs proxy et aux pare-feu, mais toute autre préoccupation est la bienvenue. Devrais-je rester du côté sûr et avoir juste un paramètre d'URL tel que action = valider | curate | draft?

Juan Mendes
la source
6
Je cite à nouveau le RFC 1925 : "Dans la conception de protocole, la perfection a été atteinte non pas lorsqu'il ne reste plus rien à ajouter, mais lorsqu'il ne reste plus rien à enlever." - Si cela fonctionne, il n'y a aucune raison d'ajouter à http.
4
Rien de mal, tant que vous réalisez que vous utilisez maintenant un protocole personnalisé et non pas HTTP.
user16764
10
@ user16764 "L'ensemble des méthodes communes pour HTTP / 1.1 est défini ci-dessous. Cet ensemble peut être développé, mais des méthodes supplémentaires ne peuvent pas être supposées partager la même sémantique pour des clients et des serveurs étendus séparément." w3.org/Protocols/rfc2616/rfc2616-sec9.html Par conséquent, il est autorisé et il est toujours HTTP
Juan Mendes
À mon humble avis, il n’ya rien à ajouter / supprimer de HTTP puisque les définitions de méthodes stipulent que l’utilisation de méthodes personnalisées est déjà acceptable dans la portée de HTTP / 1.1, mais qu’on ne peut pas s’attendre à partager la même sémantique. Je suppose donc que les points de @MichaelT et Juan Mendes être un peu apaisée
Prof83

Réponses:

42

L'une des contraintes fondamentales de HTTP et de la fonctionnalité de conception centrale de REST est une interface uniforme fournie par (entre autres choses) un petit ensemble de méthodes fixes qui s'appliquent universellement à toutes les ressources. La contrainte d'interface uniforme présente un certain nombre de points positifs et négatifs. Je cite de Fielding libéralement ici.

Une interface uniforme:

  • est plus simple.
  • sépare les implémentations des services qu'elles fournissent.
  • permet une architecture en couches, y compris des éléments tels que les équilibreurs de charge HTTP (nginx) et les caches (vernis).

D'autre part, une interface uniforme:

  • dégrade l'efficacité, car les informations sont transférées sous une forme normalisée plutôt que spécifique aux besoins d'une application.

Les compromis sont "conçus pour le cas courant du Web" et ont permis la création d'un vaste écosystème offrant des solutions à de nombreux problèmes courants dans les architectures Web. L'adhésion à une interface uniforme permettra à votre système de tirer parti de cet écosystème, tandis que le rompre rendra la tâche plus difficile. Vous voudrez peut-être utiliser un équilibreur de charge tel que nginx, mais vous pouvez désormais utiliser uniquement un équilibreur de charge comprenant les fonctions DRAFT et CURATE. Vous voudrez peut-être utiliser une couche de cache HTTP comme Varnish, mais vous ne pouvez désormais utiliser qu'une couche de cache HTTP comprenant DRAFT et CURATE. Vous voudrez peut-être demander de l'aide à quelqu'un pour résoudre un problème de serveur mais personne d'autre ne connaît la sémantique d'une demande CURATE. Il peut être difficile de modifier les bibliothèques de vos clients ou serveurs préférés pour comprendre et implémenter correctement les nouvelles méthodes. Etc.

La bonne * façon de représenter c'est comme une transformation de l' Etat sur la ressource (ou de ressources connexes). Vous ne rédigez pas de publication, vous ne modifiez pas son draftétat trueou vous ne créez une draftressource contenant les modifications et les liens vers les versions précédentes. Vous ne CURATEZ pas un message, vous transformez son curatedétat en trueou créez une curationressource reliant le message à l'utilisateur qui l'a organisée.

* Correct en ce sens qu'il suit le plus étroitement les principes architecturaux REST.

Rein Henrichs
la source
Merci pour les commentaires sur l'équilibrage de charge, je vais certainement regarder cela. Connaissez-vous une ressource qui indique si les méthodes personnalisées sont acceptables ou non?
Juan Mendes
2
Je ne vois aucun avantage aux méthodes personnalisées à moins qu'elles ne fassent partie d'une extension largement prise en charge telle que WEBDAV (et même alors, pas tellement), de sorte que je ne me suis jamais penché sur la question. Je recommanderais simplement que vous traitiez ces modifications comme des transformations d'état. Le Web fonctionne très bien avec les méthodes que nous avons déjà. Il n'y a vraiment aucune bonne raison d'en rajouter, à moins que cela ne fasse sens dans l'interface uniforme (comme PATCH).
Rein Henrichs
5
Je vois l’avantage de concevoir comment vous voulez que votre service HTTP fonctionne pour vous-même. cependant "des méthodes supplémentaires ne peuvent pas être supposées partager la même sémantique" - Assez bien, MAIS il fait toujours partie de la portée de HTTP / 1.1. Par conséquent, les pare-feu, les mandataires, les équilibreurs de charge, etc., devraient permettre cette possibilité s'ils ne le font pas. Ne mettent-ils pas correctement en œuvre HTTP / 1.1?
Prof83
Vous avez probablement raison depuis le point de vue reposant, cependant, je ne vois pas pourquoi les verbes personnalisés devraient poser problème. Tous les outils doivent les traiter de la même manière que le POST, c'est-à-dire "la ressource change probablement et c'est tout ce que nous savons".
Maaartinus
7

Je préférerais les concevoir comme des sous-ressources, sur lesquelles vous effectuez une demande POST.

Considérons que vous avez une ressource sur /instance/type/1, je voudrais que la représentation de cette ressource transmette quelques liens vers des «actions» pouvant être effectuées sur la ressource, telles que /instance/type/1/draftet /instance/type/1/curate. En JSON, cela pourrait être aussi simple que:

{
    "some property":"the usual value",
    "state": "we can still inform the client about the current state",
    "draft": "http://server/instance/type/1/draft",
    "curate": "http://server/instance/type/1/curate"
}

Cela permet au client d’être très explicite sur ce qui doit se passer lors de la demande POST au lien fourni par le curatemembre. La ressource publiée ici pourrait inclure des arguments détaillant l'événement qui infligerait peut-être une transition d'état.

L'adoption d'une approche «naïve» consistant à passer d'un état possible à l'autre d'une ressource présente l'inconvénient de ne pas capturer les événements qui ont conduit à ces transitions.

Les transitions d'état se produisent généralement en réponse à des événements spécifiques, et je préfère capturer ces événements plutôt que de laisser le client décider que quelque chose se trouve maintenant dans un "état" spécifique. Cela rend également la validation beaucoup plus difficile. De plus, vous ne pourrez capturer aucun «argument» à moins de décrire également ceux de l'état lui-même. Et puis cela devient tout nauséeux quand du code change ceux sans transition d'état réel, et la validation requise, et tout cela devient rapidement un gâchis.

Dave Van den Eynde
la source
Bonne réponse. Pouvoir fournir des arguments pour les transitions d'état et faire en sorte que le serveur les encapsule et les gère, est de loin la meilleure approche.
Thomas W
C'est ce que fait actuellement la société (VMware). GET on /vms/some-idrenvoie des liens vers des actions telles POST /vms/some-id/restartque nous l’utilisons pour déterminer si les actions doivent être activées ou désactivées. J'ai une relation d'amour / haine avec HATEOAS :)
Juan Mendes
Cela aurait tellement plus de sens si l'action entreprise était le verbe de la requête par rapport à un paramètre de requête aléatoire, un segment de chemin de ressource ou une propriété de corps.
Matthew Whited
Vous ne pouvez pas créer de lien vers un verbe.
Dave Van den Eynde
6

Je pense que la méthode HTTP personnalisée est le meilleur moyen d'implémenter des actions d'entité. L'ajout de l'action au corps de l'entité (POST) ne semble pas correct, cela ne fait pas partie de votre entité (bien que le résultat puisse y être enregistré). De plus, en utilisant les méthodes HTTP personnalisées, les mandataires pourraient déterminer leurs actions sans avoir à analyser le corps de l'entité.

C'est comme CRUD, vous voudriez toujours les implémenter, mais vous avez également votre propre ensemble d'actions spécifiques (par entité). Je ne vois vraiment pas quel serait le problème pour les prolonger.

Aussi @Rein Henrichs "Vous ne rédigez pas de publication, vous transformez son état brouillon en vrai ou vous créez un brouillon", cela me semble faux. Une draftspropriété serait utilisée pour la sauvegarde persistante de l'état et non pour la transformation. Les actions ne donnent même pas nécessairement un "état", ni ne sont enregistrées dans une propriété. Créer une entité séparée pour chaque état / transformation semble encore plus flou. Essayez de conserver la même référence (URI) à l'entité.

Robert de W
la source
1
C’est un point juste, bien que largement en désaccord, je peux voir le raisonnement derrière cela et je ne suis pas d’accord avec le vote à la baisse (surtout sans que l’électeur n’ait commenté). Prenons l'exemple de la gestion des exceptions PHP. "La meilleure pratique" semble vouloir utiliser des types Exception spécifiques pour suggérer le type d'exception, même en ignorant le message réel tel que RuntimeException vs BadMethodCallException. Alors, pourquoi s'opposer si largement à l'utilisation de DRAFT si l'utilisation de méthodes personnalisées est déjà considérée comme faisant partie de la portée de HTTP / 1.1? Et les équilibreurs de charge et les procurations doivent vraiment être accepter cette possibilité, ainsi
Prof83