Published by

Il y a 9 ans -

Temps de lecture 15 minutes

POST vs. PUT : la confusion

Aujourd’hui, de plus en plus d’applications web disposent d’une API. La pratique de SOAP étant jugée trop glissante (surtout avec les interfaces liquides), c’est le REST qui se répand.

Ce style d’architecture reposant sur HTTP, comprendre la norme HTTP est essentiel.

Cependant, les mauvais usages et autres anti-patterns sont à l’affût, prêts à se jeter sur les concepteurs et développeurs d’API. Dans cet article, nous nous attacherons à démêler une confusion entre PUT et POST.

Comme remarqué par John Calcote, beaucoup ont été tentés de faire un mapping naïf entre CRUD et les verbes HTTP :

  • Create = PUT
  • Retrieve = GET
  • Update = POST
  • Delete = DELETE

Et une variante très répandue :

  • Create = POST
  • Update = PUT

Certains seront peut-être chagrinés d’apprendre que jusqu’en 2010, il n’y avait que 3 verbes HTTP dédiés au CRUD, et que POST n’a jamais fait partie et ne fera jamais partie d’entre eux.

Posez vos boucliers, je n’ai pas dit que nous ne pouvions pas créer ou mettre à jour une entité avec POST ! Mais comme dans HTTP, et à fortiori dans une API RESTful, la sémantique est très importante et a un impact sur le design de l’API, POST peut avoir le rôle de création , mais n’est pas présenté comme tel. Nous allons devoir y regarder de plus près.

Les mauvaises pratiques

Voici la liste non exhaustive des mauvaises pratiques autour de PUT et POST :

PUT pour modifier uniquement, POST pour créer

Erreur commise dans le but de « clarifier » les rôles respectifs de PUT et POST, afin que les « débutants » comprennent vite leur API. Également commise par ceux qui trouvent POST bien pratique pour créer, et qui ont cantonné PUT à un rôle par défaut (par méconnaissance du verbe PUT ?). Un inconvénient de cette pratique, si on ne connait pas le récent verbe PATCH, est qu’on ne peut pas faire de mise à jour partielle via POST alors que c’est très pratique et largement toléré. Nous verrons plus bas que si PUT n’est pas utilisé pour créer, cela ne doit résulter que d’une contrainte.

POST utilisant l’URI de l’entité à créer

Probablement le plus grave. Ceci constitue à la fois une violation de la définition de POST et une ignorance totale du rôle de PUT. Dans le cas où POST crée une ressource, le corps de la requête contient soit l’entité, soit des informations permettant de la créer, mais l’URI est toujours une URI tierce capable de traiter la demande.

Exemple de comportement non conforme :
POST /clients/123
> ...
> ...
< 201 Created
> GET /clients/123
< 200
< ...
< ...

Exemple de comportement conforme :
> POST /clients/create
> ...
> ...
< 201 Created
< Location: /clients/123
> GET /clients/123
< 200 OK
< ...
< ...

POST qui crée une entité sans renvoyer le header « Location »

Le code retour 201 étant facultatif mais conseillé ; hé oui, où est l’entité créée ou modifiée ? En renvoyant le header Location, en réponse à un POST supposé créer une ressource, je permets au client de connaître son identifiant.

PUT qui renvoie un header Location

C’est superflu, vu qu’une requête PUT se fait sur l’URI de l’entité à créer. Si par exemple je devais compléter cet échange :
> GET /clients/123
< 404
> PUT ???
> ...
< 201
> GET /clients/123
< 200
< ...

Les points d’interrogation ne peuvent être remplacés que par « /clients/123 », du coup pas besoin de header Location.

PUT partiel

On doit fournir une entité complète dans le corps d’une requête PUT

POST omnipotent, PUT inutilisé voire inutilisable

Cela revient à supprimer la sémantique de PUT et POST, et à la faire porter entièrement à l’URI et à ses paramètres. Un peu comme SOAP, un peu comme les débuts erratiques du web où toutes pages d’un site étaient servies par /servlet/Toto?page=truc&action=toutgerer&jenpasse&desmeilleures

POST pour créer alors qu’on connait l’identifiant de l’entité à créer

Si l’identifiant de l’entité à créer est prévisible, PUT est plus approprié car nous avons alors les deux conditions nécessaires pour faire un PUT :

  • avoir une entité complète (création)
  • avoir l’URI de l’entité (grâce à l’identifiant)

Mais alors comment PUT et POST sont-ils conçus pour fonctionner ?

PUT

Regardons la norme HTTP. D’après la RFC 2616 (HTTP methods), PUT sert à

Créer une entité :
  • L’URI doit être celle de l’entité à créer
  • Si l’entité dans la requête est acceptée et créée côté serveur, le serveur doit renvoyer un code 201 (created).
  • Si l’entité peut avoir plusieurs URIs (exemple : /script/v1.2 ou /script/current), le serveur peut donc définir ces URIs alternatives comme pointant sur la nouvelle entité
Modifier une entité :
  • Si une entité avec la même URI que celle de la requête existe déjà, l’entité de la requête devrait la remplacer.
  • Ce n’est pas une création, le code retourné par le serveur en cas de succès doit être 200 (OK) ou 204 (No content). En effet, en pratique un PUT va très rarement générer une réponse avec un contenu.
Dans les deux cas :
  • Une incompréhension des header Content-* de la part du serveur doit générer une erreur 501 (not implemented) car il n’a pas le droit de les ignorer. Les autres cas d’erreur devraient également donner un code cohérent, voire un message d’erreur cohérent.
  • L’URI du PUT est celle de l’entité à créer/mettre à jour.
  • Le corps de la requête PUT doit contenir l’entité complète.
  • La redirection est possible, mais doit être permanente (code 301). Libre au client de suivre la redirection, mais s’il s’arrête là le PUT n’est évidemment pas effectif. Ce côté définitif de la redirection est nécessaire du fait que l’URI doit désigner l’entité, et non pas un processus ou action qui prendrait en charge la requête. On ne redirige donc que si on veut indiquer un changement d’URI. Il faut donc s’attendre à ce qu’une future requête accède directement à l’URI indiquée dans le précédent 301.

Détail qui a son importance, la réponse à un PUT n’est pas cachable car dépendant intrinsèquement du contenu de la requête ! Vu que la réponse est vide dans 99% des cas, ceci n’est qu’un détail logique.

Enfin, deux requêtes PUT identiques (même contenu, même URI) laissent le système dans le même état que si une seule avait été lancée (idempotence). Un détail ne devra pas nous échapper : on doit répondre 200 ou 204 à la seconde si on a répondu 201 à la première ; si James Bond ne meurt que deux fois, une entité n’est elle, créée qu’une fois.
> GET /clients/123
< 404
> PUT /clients/123
> toto
< 201
> GET /clients/123
< 200
< toto
> PUT /clients/123
> toto
< 204
> GET /clients/123
< 200
< toto
> PUT /clients/123
> poum
< 204
> GET /clients/123
< 200
< poum

Ci-dessus, nous voyons que le 201 n’est renvoyé que la première fois, à la création. 200 aurait été acceptable à la place de 204, mais 204 signale explicitement que la réponse n’a pas de corps, alors qu’avec un 200 le client le découvre.

Conclusion : PUT est bien un double verbe CRUD, capable de créer ou de modifier en intégralité l’entité désignée par l’URI. En pratique, PUT peut être écarté comme verbe pour la création car notre application ne permettra pas (politique de sécurité, contrainte technique ou contrainte fonctionnelle) à un client de connaître à l’avance son URI.

POST

Toujours d’après la RFC 2616, POST sert à :

  • annoter des ressources existantes
  • poster un message au sens « forum » du terme
  • envoyer des données à un processus qui saura les prendre en charge
  • ajouter des données dans une base de donnée

Vous trouvez ça flou ? La RFC confirme votre impression : c’est le serveur qui détermine ce que nous devons faire d’un POST. Donc, pas de sémantique forte associée à ce verbe.

Comme pour le PUT, le POST doit renvoyer le statut 200 si la réponse contient une entité, 204 si elle est vide.

Maintenant, vous aurez peut-être une question : la création en POST, nous n’en avons pas parlé ! Ai-je raté quelque chose ?

Pas de panique : il y a bien une petite phrase pour dire que si une entité est créée suite à une POST, la réponse a le statut 201 et devrait également indiquer dans le header Location l’uri de la nouvelle entité.

On voit donc que la création d’entité n’est qu’un rôle annexe de POST, il n’y a donc aucune raison de l’introniser « verbe CRUD pour la création » !

Le problème pratique

Avec de telles définitions, les concepteurs d’API se sont vite trouvés embarrassés : d’un côté, un PUT qui permet create/update mais avec une entité complète ; de l’autre, un POST dont la sémantique floue permet de tout faire. Inévitablement, POST s’est retrouvé utilisé pour les créations et mises à jour avec des informations partielles. Comme on ne peut pas toujours connaître à l’avance l’URI de l’entité à créer, POST a donc pris fréquemment le rôle de create/update : on demande une création avec les informations postées, et la nouvelle URI est dans la réponse.

Ce dernier point marque une carence du protocole : il n’y a pas de moyen, en HTTP, de mettre à jour une entité connue, en la désignant directement par son URI (comme avec PUT), avec juste le différentiel d’informations. Avec POST, il faut passer par une URI tierce, qu’on appellera un handler, une action, un processus, etc. qui lui prendra la demande en charge et inventera un sens contextualisé pour POST. Et ce même si nous connaissons l’URI de l’entité à modifier ! Il n’y a pas moyen… enfin c’était le cas jusqu’en 2010.

Heureusement, à partir de cette année là, la RFC5789 a introduit un nouveau verbe : PATCH. Le gros avantage, c’est qu’on peut désormais « patcher » une entité, c’est à dire la modifier partiellement quand on connait son URI. L’inconvénient, d’après moi, c’est que POST perd un rôle qui était clair et se retrouve à prendre « le reste », ce que les autres verbes ne prendront pas par soucis de respect de leur sens.

Alors si tout cela est une histoire de sémantique, pourquoi n’imposerions-nous pas les rôles des différents verbes HTTP pour que nos APIs soient plus claires ?

Le rôle central de la sémantique

Dans le protocole HTTP, la sémantique a un rôle déterminant sur la manière dont les différents éléments (matériels ou logiciels) doivent agir.

La respecter implique de :

  • s’assurer que les autres éléments soient cohérents dans leur manière d’agir et que nous n’obtiendrons pas des résultats aberrants.
  • permettre que n’importe quel élément inséré qui touchera à des requêtes ou réponses HTTP puisse agir de manière performante et optimisée. La RFC fourmille de suggestions sur ce que devraient faire ou ne pas faire les proxies, par exemple.

La discoverability est un aspect intéressant des APIs REST, qui se base sur le formalisme des éléments du protocole.

La discoverability est la qualité d’une API à pouvoir être découverte par un client à partir d’indices sémantiques. Si vous avez entendu parler de « web sémantique », vous avez une bonne idée de comment permettre la discoverability dans une API. L’idée est de découvrir les URIs de l’API à partir d’une ressource référence et de leur donner des rôles

Comment ? Je vous conseille de lire REST : Richardson Maturity Model qui lui-même fait référence à Richardson Maturity Model (par Martin Fowler). Vous y trouvez, au niveau 3 du Richardson Maturity Model, des exemples concrets qui montrent comment dans REST, une ressource permet d’en découvrir d’autres.

La sémantique complète n’est donc pas portée par les seuls verbes : les headers la modulent, la sémantique des liens (leur rôle) la précisent.

Les verbes HTTP donnent donc un sens très formel, qui devrait être précisé. Mais comment créer une sémantique applicative cohérente si le sens premier des verbes n’est pas respecté ?

Si vos APIs ne sont pas RESTful (ce qui est le cas de 98% des APIs qui se disent RESTful), il reste nécessaire de respecter le minimum de sens porté par les verbes HTTP pour tirer parti au maximum de l’architecture induite.

Le sens minimaliste intrinsèque des verbes HTTP (indépendamment de la sémantique donnée par les ressources) est actuellement un standard respecté largement : le simple fait de naviguer sur le web, c’est utiliser une « API » RESTful.

Si le respect du standard semble déjà une bonne raison, nous pourrions également ajouter les conventions qui rendent le développement, la maintenance et la communication autour d’une application possible : vous viendrait-il à l’esprit de créer une classe Java avec des getters dont le préfixe est « set » ou des setters dont le préfixe est « get » ? Pourtant me direz-vous, il suffit de le préciser dans la javadoc… Avec les verbes HTTP, c’est pareil. Il est possible de faire n’importe quoi et de le documenter, mais mieux vaut garder les conventions établies par les RFCs et déjà respectées par ailleurs.

Impact sur les APIs HTTP

Maintenant que nous sommes convaincus que la différence PUT/POST n’est pas une simple vue de l’esprit, que faire ?

Nous distinguerons les simples APIs HTTP, qui ont l’inconvénient d’avoir le client lié à l’organisation des ressources sur le serveur, et les APIs RESTful, qui bénéficient du découplage permis par les hypermedias.

APIs HTTP

Si vous avez des API exposées à l’extérieur qui ne respecteraient pas la norme, voyez si vous pouvez assurer une migration en profitant d’un refactoring ou d’une réorganisation des applicatifs clients. Si aucune occasion se présente, il est peu probable que votre client accepte de changer la manière de consommer votre API juste parce que vous avez ignoré la RFC.

Par contre, n’hésitez pas à introduire le nouveau formalisme pour toute nouvelle ressource exposée, même dans des API existantes. Vous éduquerez les développeurs au plus tôt sur la nouvelle manière de faire sans perturber les consommateurs des ressources existantes.

APIs RESTful

Si vous avez opté pour du RESTful, vous devriez rencontrer moins de problèmes. Même si le découplage permis par l’architecture REST vous permet de changer pas mal de chose côté serveur sans perturber le client, voyez au cas par cas si

  • le client consomme bien votre API de manière RESTful
  • la ressource permet de changer facilement le verbe (exemple : la méthode pour accéder à une ressource liée est précisée dans la ressource parente)

J’ai conscience que peu de gens imaginent la flexibilité réelle d’une API RESTful, et qualifient à tort une simple API HTTP de RESTful, je vous conseille donc la visualisation de Building Hypermedia APIs with HTML (Jon Moore). Cette vidéo qui sort largement du cadre de la confusion PUT/POST nous montre une mise en œuvre d’une API RESTful. Une autre vidéo de l’auteur montrant la mise en œuvre d’une API RESTful avec des documents XHTML a été supprimée de Viméo, mais le court article Thoughts on hypermedia apis donne l’esprit original. Quel que soit la vidéo, on y voit comment REST permet de dé-corréler le client et la structure des ressources coté serveur.

Conclusion

Nous avons donc vu que le mapping CRUD ⟷ verbes HTTP n’existait pas, et que PUT et POST avaient chacun leurs rôles bien définis. Bien qu’en pratique il sera plus facile de créer une ressource avec POST, il faudra bien veiller à ce que le POST crée une ressource liée dont il retournera l’uri (Header Location) et à ne pas oublier qu’implémenter la création avec PUT reste possible. Si créer avec PUT est possible, faites-le car c’est plus naturel (URI ressource ressource créée = URI de la requête PUT).

Nous avons vu que le respect de la distinction PUT/POST avait une influence sur la gestion des flux réseau, et sur le design des APIs. Également, le rôle de POST est beaucoup plus flou et « free style » depuis l’apparition de PATCH. L’idéal serait donc d’utiliser PATCH pour les mises à jour partielles, PUT pour les créations et mises à jour complètes, et POST pour les créations complètes lorsque PUT n’est pas possible ainsi que tout ce qui n’est pas faisable avec les autres verbes. Le mapping CRUD ↔ verbes HTTP semble inutile, car en suivant les RFCs on aboutit toujours à quelque chose de juste. Il suffit juste de s’interroger, avant chaque usage de POST, si un autre verbe ne collerait pas mieux. Et si ce n’est pas le cas, et bien… utilisons POST !

Enfin nous avons entraperçu un sujet parallèle, à savoir que quasiment personne prétendant faire du REST n’en fait vraiment, alors que les avantages sont évidents (découplage libérant le serveur de contraintes empêchant l’évolution et permettant au client de ne pas être impacté par chaque ajustement côté serveur).

Published by

Commentaire

19 réponses pour " POST vs. PUT : la confusion "

  1. Published by , Il y a 9 ans

    Une raison historique pour l’utilisation de POST partout est la mauvaise configuration ou l’absence de support des autres verbes par les serveurs proxy. Et il est bien possible que PATCH rencontre encore des difficultés (même si ça commence a dater)

    la solution classique est d’encoder le verbe réel dans les query params.

    Je trouve assez intéressant que l’URI d’exemple utilisée pour POST contienne un verbe ( POST /clients/creat). les préconisations classiques des API restful sont de n’avoir que des noms dans les URI (la convention classique est que POST /clients est une création d’un élement dans le namespace « clients »). Ca mériterait d’être développé dans un futur article :D

  2. Published by , Il y a 9 ans

    Oui, j’avoue, on rencontre encore malheureusement des services qui ne supportent pas PATCH. On peut pousser l’upgrade, mais en attendant, POST a de beaux jours devant lui.
    Le verbe sur l’URI du POST est un exemple alternatif de ce qui est fait habituellement. Ce sont les rôles de POST indiqués RFC qui m’ont incité à faire ce choix. Je viens de supprimer 10 lignes à cette réponse pour éviter de provoquer les tl;dr, tu as raison un autre article s’impose !

  3. Published by , Il y a 9 ans

    « La pratique de SOAP étant jugée trop glissante (surtout avec les interfaces liquides),  »

    Qu’entendez vous par « interface liquide » ?

  4. Published by , Il y a 9 ans

    Les interface liquides sont les interfaces dont le flot de disposition s’adapte au contenu et aux dimensions du conteneur, par opposition aux interfaces en grilles. Ça n’a aucun rapport direct avec l’article, c’est juste pour la boutade à propos de SOAP ;)

  5. Published by , Il y a 9 ans

    La sémantique du REST est trop sophistiquée pour un environnement « API d’entreprise » où dominent un public de métiers et d’urbanistes (ou d’architectes d’entreprise), ce qui est normal puisqu’on se situe à l’échelle d’un choix d’entreprise.
    Ce public ne se soucie pas de ces subtilités sémantique et se focalise sur ce qu’il appelle des « taches automatiques » issues de la modélisations métiers. A l’issu de chaque tache automatique, est attendu un résultat exploitable (fourniture d’informations ou changement d’état du système). C’est tout ce qui les intéresse. Le verbe, il s’en foutent complètement et le type d’exposition REST versus SOAP ils s’en foutent également tant que les contraintes de perf sont satisfaites.
    Cela dit, un WSDL RESTe plus lisible pour un tel public que la doc REST (… enrichie avec ton rappel à l’ordre) et le XSD qui l’accompagne.
    ;-)

  6. Published by , Il y a 9 ans

    « quasiment personne prétendant faire du REST n’en fait vraiment » -> +100000

    A noter quelques points non mentionnés d’utilisation.

    – POST est utilisé pour créer une nouvelle ressource dans un conteneur. Le client fournit alors un header Slug qui contient un potentiel nom souhaité pour la ressource, que le serveur essaiera de respecter tant bien que mal. Ex: un POST sur /folder avec en Slug: « filename ». Si la ressource /folder/filename existe deja, le serveur peut alors créer la ressource avec et retourner en Location: /folder/filename123

    – POST est aussi utilisé pour faire une opération de type append. Cela permet de rajouter du contenu a la suite d’une ressource existante. Ca peut paraître étrange sur une API JSON car on voit mal comment on peut faire un append d’un JSON sur un autre JSON (un PATCH serait plus approprié sur du JSON). Dans le web sémantique des données liées c’est utile car les ressources REST sont une liste de triples (sujet/relation/objet). Du coup cela permet des choses intéressante comme la possibilité de créer une ressource de type « inbox ». On peut donner les droits de faire un append à un tiers sans forcement lui donner les droits de faire un GET sur la ressource. Du coup il pourra rajouter du contenu a une ressource sans pour autant être capable de voir ce que d’autres tiers ont rajouté.

    – On utilise aussi MKCOL pour créer une collection / un conteneur / un dossier. L’origine provient de webdav.

    Ces quelques exemples sont utilisés sur les nouveaux protocoles du W3C comme Linked Data Platform.
    La vision de Tim Berners Lee est d’utiliser le web comme une immense base de données commune de ressources liées entre elles grace au RDF. Imaginez une sorte de grosse base document genre MongoDB, sans aucun problème de scalabilité puisque basée sur http. Imaginez un filesystem unix distribué ou les chemins sont des URI http et ou il est possible de faire un chmod.
    Voir http://www.w3.org/DesignIssues/CloudStorage.html
    Le web sémantique n’a jamais réellement pris dans le grand public jusqu’a présent a cause du manque de protocoles pour gérer l’aspect social. Aujourd’hui c’est en train de changer avec WebID et WebAccessControl.
    A lire sur le sujet:
    http://myprofile-project.org/thesis/manuscript_en.pdf

  7. Published by , Il y a 9 ans

    N’oubliez pas de migrer mon commentaire aussi :-)

  8. Published by , Il y a 9 ans

    1/ Pour une API REST, la plupart du temps, on ne connait pas l’URI de la ressource que l’on veut créer. D’où l’utilisation de POST.

    2/ Personnellement j’évite les verbes d’actions dans mes URI

    Mauvaise utilisation :

    POST /clients/create
    201 Created
    Location: /clients/123

    Bonne utilisation :

    POST /clients
    201 Created
    Location: /clients/123

    J’aime aussi mettre mes ressources toujours au pluriel

    3/ « Si vos APIs ne sont pas RESTful (ce qui est le cas de 98% des APIs qui se disent RESTful), il reste nécessaire de respecter le minimum de sens porté par les verbes HTTP pour tirer parti au maximum de l’architecture induite. »

    Je doute que ce soit encore le même pourcentage 6 ans après !? Beaucoup d’API se sont améliorées, et personnellement je n’ai pas utilisé un seul service RESTful récent qui faisait n’importe quoi. Je pense que le chiffre est complètement faux;

    Merci pour ce billet, ça nous rappelle que PUT n’est pas que pour mettre à jour et POST pas que pour créer une ressource

  9. Published by , Il y a 9 ans

    Je ne crois pas que ça soit un problème de sophistication. D’après ce que vous dites, ça serait plutôt l’absence de software designer entre les développeurs métier et les urbanistes. Des entreprises ont fait le choix de faire confiance aux architectes et/ou software designer, et ont leur résultat métier fournis par des services RESTful. Et ils bénéficient d’une flexibilité dans les évolutions qui sont caractéristiques de REST.
    Ceux qui sont restés sur SOAP en payent le prix au bout d’un moment.
    Heureusement, de plus en plus d’entreprises cessent de se focaliser sur le « get job done » et s’intéressent au « how to get it right ». Parce que s’intéresse aux résultats à court terme n’a jamais eut que des avantages, mais c’est un autre sujet.
    Enfin je dirais que ce qui manque certainement aux développeurs métier, c’est un vrai client REST qui leur permet de se focaliser sur l’accès aux ressources et la navigation dans celles-ci plutôt que de se demander quel verbe utiliser.

  10. Published by , Il y a 9 ans

    Sur le POST avec Slug, attention, je n’irais pas consacrer cette utilisation. Si le client connaît l’URI finale, il peut faire un PUT dessus. Si le fichier existe déjà (par rapport à votre exemple folder/fichier), la ressource cible sera écrasée (comme sur votre système de fichier). Si une ACL interdit à l’utilisateur de le faire, soit parce qu’il n’a pas le droit, lui, d’écraser le fichier, soit parce que c’est interdit par votre application de manière générale, alors une erreur 4XX sera renvoyée. Le client prévenir cette erreur en envoyant OPTIONS sur la ressource pour savoir ce qu’il a le droit de faire dessus avant d’envoyer la charge réelle.
    POST avec Slug est une alternative possible. Elle a l’inconvénient de ne pas se baser sur ce qui existe déjà dans HTTP et de charger le verbe POST de sémantique custom à documenter. Et comme vous le faites remarquer, POST doit renvoyer le header Location s’il a créé une ressource.

    Pour le append, si PATCH est disponible sur vos infra, c’est son rôle (https://tools.ietf.org/html/rfc5789) ! Pourquoi ne pas l’utiliser ?

    MKCOL est du WEBDAV comme vous le faites remarquer, donc il sort du contexte de l’article. En effet, à partir du moment où on fait du WEBDAV, la question s’élargit car il existe de nombreux verbes. La question n’est plus « PUT vs POST » mais « quel verbe pour … ? ».

    Enfin, le Web sémantique est rendu possible plus facilement grâce à la notion HATOAS. En effet, les liens sont porteurs de sens. Une ressource hypermedia peut indiquer sur un lien quelle est la relation son l’URI. J’en parle dans l’article surtout pour montrer l’intérêt du respect des standard, mais c’est un sujet qui dépasse l’article. Je vous rejoins bien sûr l’intérêt du web sémantique.

  11. Published by , Il y a 9 ans

    On va pas refaire le débat SOAP versus REST :-), des entreprises ont également fait le choix de SOAP implémenté avec méthode et bénéficient d’une flexibilité dans les évolution. C’est une question de méthodes, une API SOAP implémenté avec méthode vaudra mieux qu’une API RESTful mal implémentée et inversement.
    L’avantage de REST était de forcer les concepteurs à se focaliser sur la ressource ce qui permettait de se réconcilier avec l’approche « Objets Métier » coté urba et architecture d’entreprise, mais les mauvais usages n’ont pas épargné le RESTful au même titre qu’ils n’avaient pas épargné le SOAP (… c’est d’ailleurs l’une des raison de ton article).
    Pour info, l’approche « Objet Métier » coté architecture d’entreprise consiste à exposer une API autour de concepts métiers fondamentaux et invariants ce qui permet leur réutilisation quelque soit l’évolution des processus métier.

  12. Published by , Il y a 9 ans

    L’utilisation de POST avec Slug a un interet lorsqu’on veut créer une ressource sur un conteneur et lorsqu’on n’a pas besoin d’être strict sur l’URI qui sera réellement allouée à la ressource. C’est
    Si on veut vraiment que l’URI soit celle que le client a choisi, alors il faut en effet faire un PUT.
    A noter qu’il existe aussi un header qui permet de demander au serveur de n’autoriser que la creation. De cette manière on a pas besoin de faire un OPTIONS en amont lors d’un PUT si on veut s’assurer qu’on n’override pas une ressource qui existe deja.

    Pour le PATCH je ne peux pas vraiment répondre mais je pense que c’est parce qu’il faut définir des sémantiques de payload sur un patch pour qu’il puisse se comporter comme une opération d’append. Dans le web sémantique, le payload d’un patch est généralement une requête SPARQL d’update, qui peut effectivement rajouter du contenu. Cela semble probablement plus naturel de pouvoir rajouter du contenu avec POST et cela permet aussi de pouvoir mieux gérer les autorisations en fonction du verbe. Par exemple on peut interdire a une personne de faire un PATCH mais l’autoriser a faire un POST pour rajouter du contenu. Si on utilisait PATCH a la fois pour modifier partiellement et pour faire un append, on serait alors obligés de parser et comprendre le payload du patch pour savoir si la mise a jour est autorisée ou non. Et il peut y avoir beaucoup de formats de payload différents donc c’est compliqué à en pratique pour gérer la majorité des sémantiques de PATCH…

    A noter que ces utilisations ne sont pas des usages personnels que je fais de REST mais des utilisations en cours de standardisation dans le monde du web sémantique. L’idée n’est pas vraiment de voir si une solution alternative existe deja mais plutot de voir si on peut créer quelque chose de mieux pour HTTP.
    Si vous pensez qu’il s’agit de mauvais usages n’hésitez pas a en discuter sur les ML du W3C :)
    http://www.w3.org/TR/ldp/#ldpc-HTTP_POST
    http://www.w3.org/wiki/WebAccessControl
    Working Group: http://www.w3.org/community/rww/

    Pour HATEOAS je ne connais pas plus que ça mais j’ai plutot l’impression que c’est un concept qui reprend des idées du web sémantique et du linked data plutot que l’inverse. Dans pas mal d’exemples HATEOAS les liens sont créés entre les entités, ce qui est un bon début, mais on voit bien qu’il manque quelques trucs importants:
    – les liens ne sont souvent pas stables car générés par les WS JSON
    – la manière dont sont déclarés les liens n’a pas l’air très standardisée et sur 2 exemples différents on retrouve des sémantiques différentes.
    – les relations ont aussi l’air d’être souvent déclarées sans namespace et d’être des relations custom pour l’appli, la ou le web sémantique encourage la réutilisabilité de sémantiques existantes via les ontologies.

  13. Published by , Il y a 9 ans

    2) L’exemple avec l’action n’est pas une mauvaise utilisation. Je l’ai donnée en exemple parce qu’elle est moins habituelle mais tout aussi valable. Cf ma réponse à Jean.
    3) Cf mon lien, sur les 98%. Si on s’en tient à la définition de Roy Fielding, aujourd’hui encore quasiment aucune API HTTP n’est RESTful. Beaucoup s’en approchent, mais ça s’arrête souvent là.

  14. Published by , Il y a 9 ans

    Pour le PATCH, cf la RFC. Il est prévu pour l’append. Le but de la RFC sur PATCH est d’affiner le rôle de POST.

    Pour distinguer l’append du create ou autre update, il y a les arguments passés en header avec PATCH (cf RFC encore).

    Enfin à propose de HATEOAS je ne saurais que trop vous conseiller la lecture de la thèse de Roy Fielding, ainsi que des précisions sur son blog. Et JSON tel-quel n’est pas un hypermedia, il n’est donc pas possible de faire une API REST avec des entités JSON en l’état. Jon Moore par exemple, a utilisé successivement XHTML puis HTML5 comme format hypermedia (la vidéo où il met en œuvre XHTML n’est plus disponible à ma connaissance). Personnellement, je serais intéressé par une modification du format JSON pour le rendre hypermedia. Le web sémantique propose une normalisation des relation qui n’est que la propriété de l’application pour Fielding. En effet, il n’y a pas besoin qu’une application obéisse à une sémantique standardisée pour être RESTful.

  15. Published by , Il y a 9 ans

    « Pour distinguer l’append du create ou autre update, il y a les arguments passés en header avec PATCH (cf RFC encore). »
    On peut faire un create avec PATCH?
    Je ne suis pas sur de comprendre de quels headers il s’agit? Si il s’agit d’un « Accept-Patch » sur lequel on se base sur le mediatype pour savoir si on a le droit de faire un update et/ou un append, cela ne marche pas quand les 2 opérations sont permises via le meme mediatype comme c’est le cas de sparql-update. Mais peut-être s’agit-il d’un autre header que je n’ai pas vu?

    C’est vrai qu’il n’y a pas besoin d’obéir a des relations standardisées pour etre RESTful, et le web sémantique n’oblige pas nécessairement à reutiliser les ontologies existantes. Mais quel est alors l’interet d’etre RESTful si cela demande à chaque fois de recoder un client pour chaque API car les relations sont différentes? Ca revient un peu au même que de ne pas vouloir reutiliser les verbes HTTP existants, avec les mêmes problèmes que ceux mentionnés dans cet article: on devient obligés de documenter les relations non standardisées de la même manière qu’on devrait documenter les usages détournés des verbes HTTP.

  16. Published by , Il y a 9 ans

    Effectivement au temps pour moi, dès qu’on fait un PATCH c’est de l’update. Je voulais dire « Pour distinguer l’update-append de l’update partielle classique ». Il y a des headers pour dire où patcher, donc on peut spécifier le fait de patcher « juste après la fin ».

    Quand à re-coder un client pour chaque application, ce n’est nécessaire totalement. Jon Moore a fait un PoC sur un client générique.
    Cependant, il rappelle, comme Roy Fielding, qu’une application RESTful n’implique pas le zero-connaissance sur l’application. Avec ce qu’a montré Jon Moore, on peut avoir à modifier la partie métier de l’appli cliente à chaque fois que des nouveautés fonctionnelles côté serveur doivent être prises en compte, mais sans modification on reste à iso-fonctionnalité le client REST générique gère tout seul la récupération des bonnes ressources. Le client métier alimente le client générique avec les relations demandées (qui sert de navigateur), et ce dernier rends les infos avec les liens et les rôles trouvés. Ainsi, le but du style d’architecture REST est respecté : la structure côté serveur peut changer, le client générique refera les requêtes nécessaires (et pourra cacher le résultat en respectant la norme comme un navigateur) afin de retrouver les infos ; seul un changement des besoins métier nécessite un changement du client métier : l’application RESTful ajoute des nouveaux rôles/entités, pour les connaître côté client il faut nécessairement les chercher… on reste dans une logique simple.

    Je reconnais au web sémantique la volonté d’aller plus loin et de standardiser des rôles communs afin de faciliter des découvertes automatiques. Cependant, REST est déjà utile sans ça. Pensez simplement au fait que sur une API HTTP non RESTful, un client générique n’est pas possible et qu’il faut recompiler le client métier à chaque réorganisation des ressources, même déjà connues (je prend l’exemple de Java avec Jersey : si la définition du chemin d’une ressource change côté serveur par exemple, on doit changer quelque chose dans le client. Une contrainte que REST élimine).

    Bref, je suis à fond avec vous si vous voulez bâtir un web sémantique sur des APIs RESTful, mais je reconnais une grande utilité à REST avant de penser au web sémantique.

  17. Published by , Il y a 8 ans

    Impossible d’imprimer les billets de votre blog. C’est bien dommage ! Et quelle régression ! Faites une feuille de style css pour le print !

  18. Published by , Il y a 8 ans

    Aldo, merci d’avoir fait remonter ce problème. On rectifie le tir au plus vite !

  19. Published by , Il y a 7 ans

    thanks..
    Its works perfectly

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Nous recrutons

Être un Sapient, c'est faire partie d'un groupe de passionnés ; C'est l'opportunité de travailler et de partager avec des pairs parmi les plus talentueux.