24 points par GN⁺ 2025-07-10 | 1 commentaires | Partager sur WhatsApp
  • Dans le texte fondateur sur REST de Roy Fielding, l’usage des méthodes HTTP ou d’API centrées sur le CRUD n’est pas explicitement défini comme une exigence, et REST mettait à l’origine l’accent sur la conception de systèmes basés sur l’hypermédia (HATEOAS)
  • Beaucoup de ce que l’on appelle des API RESTful n’implémentent pas les contraintes essentielles de REST (en particulier l’usage de l’hypermédia)
  • Une ressource ne se limite pas à une simple structure de données ou à une entité, mais englobe tout concept pouvant être identifié par une URI
  • Selon les 6 règles de Fielding, les éléments clés sont l’exploration centrée sur l’hypermédia, l’indépendance vis-à-vis du protocole et l’importance des media types
  • En pratique, en raison notamment de la commodité d’outils de documentation comme OpenAPI, la plupart des API sont conçues plus près d’un style RPC que d’un REST véritablement RESTful

Pourquoi la plupart des API RESTful ne sont pas véritablement RESTful

  • Dans son article de référence (2000), Roy Fielding présente REST (Representational State Transfer) comme un style idéal de conception logicielle pour les réseaux, et l’explique comme l’un des principes ayant soutenu le succès du Web
  • L’article ne définit pas comme obligatoires l’usage des méthodes HTTP ni une conception centrée sur le CRUD ; il souligne au contraire que, dans une approche REST, l’essentiel réside dans les transitions d’état basées sur l’hypermédia (HATEOAS), une interface uniforme et des interactions centrées sur les ressources

Hypermédia (HATEOAS) et malentendus autour de REST

  • Fielding indique clairement qu’une API sans hypermédia n’est pas RESTful
    • « Si le moteur n’est pas piloté par l’hypertexte, ce n’est pas RESTful »
  • HATEOAS désigne une approche dans laquelle le client découvre dynamiquement les actions possibles en suivant les liens intégrés dans les réponses du serveur
  • Utiliser simplement une interface HTTP/CRUD n’est pas équivalent à l’essence de REST

Malentendus fréquents sur REST

  • REST serait du CRUD (alors qu’il s’agit en réalité d’un concept plus large)
  • Une ressource serait forcément une entité (la structure de données du serveur)
  • Une API RESTful ne devrait pas utiliser de verbes dans ses URI
  • Tout cela relève de décisions de conception, sans lien direct avec l’essence de REST

Ce que signifie réellement une approche pilotée par l’hypermédia (HATEOAS)

  • L’objectif de HATEOAS est de minimiser le couplage client-serveur
  • Si la structure des URI côté serveur change, cela réduit le coût des redéploiements côté client et améliore la scalabilité et la capacité d’évolution
  • Le client découvre les actions à effectuer en suivant les hyperliens présents dans la réponse, sans dépendre de documentation ou de connaissances préalables
    {  
      "orderId": 123,  
      "_links": {  
        "self": { "href": "/orders/123" },  
        "cancel": { "href": "/orders/123/cancel", "method": "POST" }  
      }  
    }  
    
  • Comme ci-dessus, il faut que les actions (liens) soient incluses dans la réponse pour se rapprocher d’une API véritablement RESTful

Qu’est-ce qu’une ressource en REST ?

  • Une ressource est tout ce qui peut être identifié par une URI
    • Cela inclut des documents, des images, des objets physiques, des services, des concepts abstraits, etc.
  • Il n’existe pas forcément de « ressource » concrète sur le serveur ; il s’agit plutôt d’une structure de mappage abstraite accessible par URI
  • La RFC 3986 ne limite pas non plus la portée de la notion de ressource
    • Elle peut inclure des documents électroniques, des images, des sources d’information, des services, voire des personnes, des entités juridiques ou des livres

Les 6 règles d’une API RESTful selon Fielding

  • 1. Ne pas dépendre d’un protocole unique
    • L’identification basée sur les URI doit pouvoir être exploitée à travers différents protocoles
  • 2. Ne pas modifier arbitrairement les standards du protocole (par ex. HTTP)
    • On peut compenser certaines limites du standard, mais pas ajouter ou changer librement ses règles
  • 3. Se concentrer sur la définition des media types (formats) plutôt que sur la structure des URI
    • Il faut se concentrer sur le format des données et la définition des liens, sans gaspiller d’énergie sur des spécifications de chemins ou une documentation excessive
  • 4. Ne pas coder en dur une convention de nommage d’URI ou une hiérarchie fixe
    • Le client ne doit ni deviner ni figer la structure de l’espace de noms du serveur ; il faut favoriser une exploration basée sur les liens
  • 5. Ne pas exposer le type de ressource (classification interne)
    • Les types d’objets internes n’ont pas de sens pour le client ; seuls les media types et liens standard doivent être exposés
  • 6. Un signet (URI initiale) suffit ; le reste doit être découvert via les liens des réponses
    • Le client ne connaît que les media types standard, et les transitions d’état doivent toujours s’effectuer à partir des hyperliens contenus dans les réponses du serveur

Interprétation des règles et application concrète

  • Pour se rapprocher d’une API véritablement RESTful, il faut minimiser le couplage au protocole, aux URI et aux types
  • Une API doit se concentrer sur le format des données et des liens (media type) ; le client n’a pas besoin de connaître à l’avance la structure des URI ou les conventions de nommage
  • Au lieu de documenter explicitement un chemin comme /users/123/activate, il faut guider l’action au moyen d’un lien "activate" présent dans la réponse

Pourquoi les véritables API RESTful sont rares

  • La commodité d’outils comme OpenAPI ou Swagger est souvent prioritaire dans les équipes de développement
    • Ils offrent des avantages concrets : documentation automatique, génération de code, validation, etc.
  • Dans les environnements SPA où client et serveur sont développés par la même équipe, le besoin de réduire le couplage aux URI est moins pressant, ce qui rend les avantages de HATEOAS moins visibles
  • La charge d’apprentissage initiale des principes REST et la complexité de l’analyse dynamique des liens constituent aussi des obstacles pratiques importants

Conclusion

  • Selon les règles de Fielding, une véritable API RESTful doit impérativement reposer sur l’exploration dynamique par hypermédia (HATEOAS)
  • REST ne consiste pas simplement à implémenter du CRUD sur HTTP ; c’est une architecture axée sur le couplage faible, la capacité d’évolution et les transitions d’état dynamiques, à l’image des principes du Web
  • Dans la pratique, l’important peut être davantage la conception adaptée au contexte de l’équipe et à l’utilité réelle
    • Pour une API publique destinée à des développeurs externes, l’adoption de HATEOAS est recommandée ; pour une API strictement interne, un style RPC plus simple peut être plus pragmatique
  • L’essentiel est de concevoir une API facile à apprendre et difficile à utiliser de travers, sans qu’elle doive nécessairement être RESTful

1 commentaires

 
GN⁺ 2025-07-10
Avis Hacker News
  • Je comprends le fondamentalisme excessif qu’on voit ici et j’ai aussi lu avec intérêt la thèse de Fielding, mais j’ai eu l’impression que cette guerre est déjà terminée. Dès qu’on entend le terme API REST, on peut presque être sûr de ceci

    • l’API renvoie du JSON
    • les opérations CRUD sont mappées à POST/GET/PUT/DELETE
    • l’équipe débat sans fin des codes de statut HTTP appropriés, et certains codes sont utilisés différemment de la spec
    • il est aussi possible que l’endpoint de listing passe en POST pour prendre en charge des filtres complexes Comme pour Agile, CI ou DevOps, soit on s’accroche à la définition d’origine, soit on admet que le sens social a déjà changé et on utilise simplement le terme dans son acception courante
    • Je pense que si Fielding a gagné, c’est précisément parce que son raisonnement est contradictoire et en grande partie erroné. C’est le paradigme du « worse is better » du XXIe siècle. Les systèmes RPC étaient peu ergonomiques et n’ont pas réussi, par exemple Sun RPC, RMI, DCOM, CORBA, XML-RPC, SOAP, Protocol Buffers, etc. Les gens disent que REST n’est pas du RPC, mais en pratique, en Javascript on crée une fonction comme
    const getItem = async (itemId) => { ... }
    

    qui appelle

    GET /item/{item_id}
    

    et côté backend il y a une fonction du genre

    Item getItem(String itemId) { ... }
    

    avec des annotations pour décrire le mapping d’URL. Au final, c’est du RPC. La différence, c’est qu’au lieu d’un système complexe et peu intuitif, on reste sur quelque chose de plus artisanal et sous le contrôle du développeur. 80 % des problèmes viennent surtout du fait que les gens n’utilisent pas le format de date ISO 8601

    • Je ne comprends pas vraiment pourquoi certains considèrent cela comme une « bataille » et s’en préoccupent autant. Le concept de REST est utile, mais la partie HATEOAS est peu pratique et ne fait qu’ajouter des problèmes. Si on regarde le Richardson maturity model, le sommet de REST inclut des éléments comme HATEOAS. Je ne comprends pas non plus l’idée selon laquelle, sans HATEOAS, on ne pourrait pas appeler cela REST, car ce n’est pas une différence si majeure. Si HATEOAS est concrètement presque sans intérêt, alors s’obséder de cette classification fondamentaliste me paraît inutile. Richardson maturity model

    • Sur le point « les équipes débattent trop des codes de statut et les utilisent souvent différemment de la spec HTTP », il insiste sur le fait que 401 Unauthorized doit être utilisé quand l’authentification n’est pas faite, et 403 Forbidden quand il n’y a pas les autorisations nécessaires

    • J’ai plutôt tendance à demander aux gens s’ils comptent vraiment utiliser le sens de REST tel que défini dans la thèse. En général, je fais partie de ceux qui n’acceptent pas qu’on abuse de termes vides de sens. Au final, je réponds « d’accord, donc vous parlez juste d’une API web » et je passe à autre chose. La vraie différence, c’est qu’il faut ensuite identifier les bizarreries propres à chacune de ces API

    • La nuance qui compte vraiment pour moi, c’est que les « liens hypermedia » donnent l’impression d’être « génériques » grâce à différents link types, inclus dans les en-têtes HTTP ou les réponses, alors qu’en pratique le REST d’aujourd’hui fonctionne exactement pareil. Par exemple, si la conception est mauvaise et qu’il aurait fallu enable au lieu de activate, il faut quand même passer de /api/v1/account/ID/activate à /api/v2/account/ID/enable. Autrement dit, il faut forcément coder en dur quelque part le sens de toutes les actions de l’API (et il manque aussi des métadonnées annexes comme les icônes, la traduction des libellés d’action, etc.). La « généricité » de cette approche est en réalité une illusion

  • Quand j’ai dû développer ma première API HTTP il y a 13 ans, j’ai lu la thèse de Fielding du début à la fin pour comprendre ce qu’était le vrai REST, puis j’ai aussi lu RESTful Web Services Cookbook. J’ai ensuite construit une API REST en évitant les conventions de Django. C’était une sorte d’approche de cargo cult, car je ne comprenais pas vraiment quel avantage concret le vrai REST apporterait à notre service. Ce n’est qu’après encore plusieurs années à construire différentes API HTTP que j’ai fini par comprendre qu’en pratique les principes théoriques de REST n’apportaient aucun bénéfice dans le contexte réel du travail. La vision de « self-discovery » et de « compatibilité avec des clients génériques » est presque irréalisable, et la thèse de Fielding elle-même n’explique d’ailleurs pas parfaitement comment y parvenir concrètement. Pour créer une API réellement auto-découvrable, il faut des règles précises comme un « protocole de découverte d’endpoints », une « description des opérations », des « messages d’aide », etc. Et il faut au final développer des clients dédiés capables de comprendre ces règles, ce qui fait disparaître l’avantage supposé d’un client générique. En pratique, on finit donc par écrire du code spécifique à chaque serveur, que ce soit des API dédiées, du code JS ou des CLI. Et une bonne UX entre aussi en conflit avec l’idéal REST, car pour obtenir une vraie bonne UX, il faut du code spécifique à l’application côté front. On peut certes standardiser certains éléments d’UI, mais dans la réalité il est bien plus utile de construire des interfaces souples avec un langage comme JavaScript

    • Je partage ce constat sur les limites du concept d’API auto-découvrable. Un véritable client REST est pratiquement impossible à implémenter. Il faut connaître le comportement de toutes les URL, et si un nouveau comportement apparaît (par ex. /cansofspam/123/frobnicate), le client ne saura pas clairement quoi en faire. Il faudra donc soit mettre le client à jour, soit ignorer ce comportement, soit au mieux ajouter un bouton très simple du genre « Frobnicate ». En conséquence, il n’existe pas de serveur ou de client REST au sens pleinement strict. Dans la réalité, on exploite simplement des clients qui supportent l’API attendue sans véritable mécanisme de découverte

    • Une API a de multiples dimensions, ce qui la rend difficile à décrire. Les utilisateurs de l’API doivent aussi connaître la latence moyenne de réponse, les codes d’erreur sur lesquels on peut faire un retry, l’atomicité ou l’idempotence des actions, etc. HATEOAS ne permet pas de connaître tout cela. Il n’est pas nécessaire d’implémenter un REST parfait, et l’avantage fondamental de REST, c’est surtout de disposer d’un langage commun qui mappe noms et verbes sur des méthodes HTTP et des URL. Malgré cela, la conception détaillée et les arbitrages restent extrêmement nombreux. Par exemple, certaines choses autorisées par la spec HTTP sont impossibles à utiliser derrière un LB réel, et il faut aussi se préoccuper des critères de retry sur des erreurs 500, de la logique de backoff, etc.

    • Le navigateur est justement le « code générique » par excellence, et il fournit la meilleure UX que nous utilisons tous au quotidien. Le concept de REST inclut aussi le fait que le serveur puisse transmettre du code au client (même s’il existe des problèmes de sécurité, que les navigateurs et les standards ont déjà largement traités). Lien vers la section correspondante de la thèse de Fielding

    • En réalité, même dans une version affaiblie de la définition de REST, il n’y a pas tant de bénéfices. Dire qu’il faut absolument utiliser DELETE pour supprimer une ressource n’a rien de capital. Si on utilise simplement POST, en quoi cela gêne-t-il quelqu’un ?

    • Je n’ai jamais considéré que « auto-découvrable » était l’objectif, ni même quelque chose d’atteignable. Pour une conception de client simple, c’est de toute façon une attente excessive. D’ailleurs, dans le TFA, le mot « discoverable » lui-même n’apparaît pas

  • Ce style de conception d’API n’est vraiment utile que lorsque l’utilisateur et l’agent chargé d’explorer à sa place (par ex. le navigateur) peuvent parcourir l’API et interagir selon les media types et les informations de liens contenues dans chaque réponse. La plupart des API web ne sont pas conçues pour ce cas d’usage, mais pour des webapps cherchant une UI/UX spécifique. C’est un choix délibéré. Les créateurs de l’application veulent contrôler entièrement la représentation des données, le flux d’UI, etc., afin d’atteindre les objectifs du produit. La conception d’une API REST devient nécessaire quand l’utilisateur doit davantage piloter lui-même l’usage des ressources exposées par l’API. Par exemple

    • des portails publics d’information gouvernementale accessibles à tous (textes de loi, météo, registres immobiliers, etc.)
    • des portails administratifs avec divers formulaires à soumettre
    • des projets d’open data comme Wikipédia ou OpenStreetMap Ce sont des domaines où il serait pertinent d’adopter une conception d’API REST. Au fond, ceux qui insistent sur une définition stricte de REST ont souvent un bagage plus académique, tandis que ceux qui en ont un usage plus large sont plutôt des développeurs davantage centrés sur l’expérience applicative. La solution est simple : quand ce n’est pas du vrai REST, il suffit de ne pas l’appeler REST
    • En réalité, un document HTML est exactement ce cas-là. Il contient des liens vers d’autres documents, et l’utilisateur peut naviguer partout en suivant le texte de ces liens. Si c’est pour les utilisateurs, on appelle cela une UI ; si c’est pour des applications, on appelle cela une API. Si HATEOAS paraît étrange, c’est parce qu’il donne l’impression de vouloir adapter directement l’API à l’utilisateur. Mais nous profitons déjà de cela sous la forme de l’UI

    • Le concept de REST pur est très académique. Dans les projets open data ou big data, lorsqu’il faut implémenter une architecture ou des performances réelles, une approche pragmatique compte plus que le fait d’atteindre REST au sens strict. Même les universitaires doivent au final livrer des résultats, donc ils ne s’accrochent pas uniquement à un REST parfait

    • Ce type de conception d’API est utile non seulement pour des pages web, mais aussi pour créer d’autres clients. On peut récupérer une ressource en GET, extraire des valeurs via des champs ou des chemins, construire de nouveaux URI pour les manipuler, etc., et ainsi bâtir différents types d’apps, de CLI ou d’UI selon des schémas similaires. Dans le cas d’une non-SPA, on peut même l’implémenter directement en HTML ; au fond, il s’agit pour l’utilisateur (ou le user-agent) de dereference les informations contenues dans la représentation renvoyée

    • Je me demande si ce cas d’usage deviendra plus important à l’ère où l’IA consommera des API. La discoverability d’une API est bien plus utile à l’IA qu’à un développeur de webapp. MCP (protocole de contrôle immersif) montre à quel point la discoverability des outils peut être puissante. HATEOAS pourrait offrir de grands avantages potentiels même pour cette consommation d’API bare

    • Lorsqu’une API d’information publique est bien conçue, comme la documentation de l’API RESTful des services du National Weather Service américain, c’est vraiment agréable à utiliser

  • À propos de l’idée que « la charge cognitive initiale pour construire un vrai client hypermedia paraissait énorme, et qu’il semblait plus simple de hardcoder des templates d’URI (/users/{id}/orders, etc.) », j’ai moi aussi constaté empiriquement que c’était effectivement plus simple. Les principes REST purs ont, dans la grande majorité des cas, un mauvais rapport coût/bénéfice. C’est un peu comme un micro-ondes qui utiliserait un seul bouton pour tout régler — menu, mode de fonctionnement, durée — ce qui est beaucoup plus pénible que d’avoir simplement des boutons standards dont on connaît l’usage. Même le lecteur de codes moteur à deux boutons que j’utilise réellement est absurdement peu pratique à manipuler. Le fait qu’on continue à dire qu’il faut absolument lire la thèse de Fielding est encore aujourd’hui très polémique. Si c’est une bonne idée, elle devrait pouvoir être expliquée facilement de multiples façons, avec un point de vue accessible au grand public. Par exemple, personne ne dit qu’il faut absolument lire les Principia de Newton pour comprendre la physique

  • Pour qu’il y ait une vraie valeur à adopter les patterns RESTful/HATEOAS, il faut des clients capables de les comprendre. htmx: hypermedia clients intercoolerjs: hatoeas-is-for-humans

  • Les UI designers veulent contrôler l’apparence détaillée des écrans. Certaines actions possibles sur une ressource seront affichées comme de gros boutons, d’autres cachées dans un menu, et d’autres encore totalement absentes de l’UI. Si les actions sont rendues dynamiquement à partir de la réponse de l’API en fonction de chaque état, alors toutes les actions finissent par avoir la même apparence. C’est pourquoi je considère qu’une API RESTful est inadaptée à l’implémentation d’une UI frontend web classique

    • Cette affirmation contient plusieurs erreurs

      1. Les UX designers interviennent sur l’ensemble du cycle de développement produit et n’ont pas systématiquement un contrôle absolu. La position d’une action donnée dans l’UI est distincte du « state » de l’action. Autrement dit, si l’état impose une contrainte, l’UX doit suivre cette contrainte
      2. D’un point de vue architectural, encapsuler la vérification d’état peut être bien meilleur que de faire simplement if (state === something) ; un test comme if (resource.links['action'] !== null) peut être préférable. La plupart des changements d’état doivent être validés côté serveur, et n’implémenter cette logique que sur le serveur réduit aussi la complexité du front. J’ai développé des applications HATEOAS pendant assez longtemps, et je maintiens aussi HAL4J. Il y a de la complexité, mais la conception d’UI n’est pas en soi la barrière à l’entrée
    • Dans mon expérience, le développement d’une « API RESTful » a rarement été directement lié à l’UI. Si on a seulement besoin d’une vraie UI, alors l’API elle-même est inutile ; on peut simplement faire du server-driven comme autrefois avec DWR, par exemple

  • J’ai du mal à comprendre pourquoi on discute encore autant de HATEOAS alors que cela semble presque jamais utilisé en pratique. Je me demande s’il existe vraiment des endroits qui l’emploient, et quels « clients à exploration automatique » fonctionnent réellement sans connaître à l’avance les informations du serveur

    • Je rappelle qu’ACME (le protocole de Let’s Encrypt) repose sur HATEOAS. Il est en pratique utilisé par la majorité des services HTTPS. HTTP lui-même, lorsqu’il est utilisé correctement, est à l’origine un protocole HATEOAS. L’« auto-discovery » consiste à pouvoir explorer des ressources via des link types ou des choses comme next. Cela dit, le client doit quand même connaître à l’avance le sens de next. Les LLM sont aussi performants pour ce type d’exploration automatique

    • J’ai utilisé HATEOAS dans un système de vidéosurveillance de niveau entreprise. Cela gérait très bien les problèmes de version et d’autorisations au niveau de l’API. Nous utilisions aussi plusieurs RFC en parallèle. Mais le problème numéro un, c’est que les gens recherchent la « commodité » d’une façon qui détruit le modèle et finit par introduire encore plus de complexité. Et comme JSON n’est pas intrinsèquement un format hypertexte, essayer d’injecter de force HATEOAS dans application/json donnait quelque chose d’assez artificiel

    • J’utilise HATEOAS pour saisir ce commentaire, et je suis en train de poster cette réponse en ce moment même. Le « client magique à exploration automatique » qui s’en charge, c’est tout simplement le « navigateur web »

    • htmx est peut-être la tentative la plus réaliste

    • Même des standards comme OData sont à peine utilisés, et pas vraiment populaires. HATEOAS manque encore davantage de popularité et de standardisation, donc cela semble encore moins susceptible de s’étendre

  • Ce qu’on oublie facilement dans ce débat, c’est le type de consommateur de l’API backend. REST et HATEOAS prennent généralement plus de sens lorsqu’ils sont consommés par des tiers qui ne possèdent pas directement le backend. Par exemple, le consommateur final d’une page HTML traditionnelle est l’utilisateur du navigateur. Plus récemment, MCP est apparu parce qu’il fallait de la « discovery et interprétation » pour divers API JSON RPC. En revanche, quand le front et le backend sont couplés en 1:1, les avantages de REST ne valent souvent pas le coût. Il faut documenter et spécifier les choses de façon plus générique, alors qu’en pratique des outils qui ignorent la separation of concerns pour gagner en productivité (comme trPC) peuvent souvent être plus utiles. En phase de prototypage, l’intégration end-to-end est rapide

  • Concernant l’affirmation selon laquelle HATEOAS et des références de schéma (XSD, JSON Schema, etc.) permettraient des clients d’exploration dynamique, en pratique des fonctionnalités comme additionalProperties dans JSON Schema ne font que reproduire le problème à l’origine. Je trouve plus robuste de transmettre la documentation hors bande. Dans ce cas, pourquoi ne pas simplement fournir dans _links un lien vers la documentation Swagger, puis laisser le client exploiter cette information de chemin self ? Mais si c’est le cas, pourquoi _links devrait-il exister ? Si un client est capable de traiter un document JSON aussi complexe, alors des templates Swagger offrent au contraire une densité d’information et une dynamicité bien supérieures. Avec de simples liens CRUD, on ne décrit pas suffisamment toute l’API, et il est impossible de tout couvrir avec JSON Schema

  • Si on appelait simplement cela une API HTTP, tout le monde serait plus heureux. REST n’a de toute façon jamais été conçu au départ pour les API. Dès l’origine, REST visait les systèmes d’information destinés aux humains, pas aux programmes