Article

L'« API REST » est un REST du pauvre

Le modèle de maturité de Richardson et le coup de gueule de Fielding : la plupart des « API REST » sont du RPC à belles URL — un REST du pauvre. Quand ça suffit.

La plupart des API qui se disent « REST » feraient grincer des dents leur propre inventeur. Roy Fielding l'a écrit noir sur blanc en 2008, visiblement excédé : sans hypermédia, ce n'est pas du REST. L'écart a un nom — et même une échelle pour le mesurer.
Escalier de maturité de Richardson : niveau 0 tunnel RPC, niveau 1 ressources, niveau 2 verbes et statuts (où s'arrête la plupart des API REST, le REST du pauvre), niveau 3 contrôles hypermédia HATEOAS (le seul niveau que Fielding appelle REST).
Le modèle de maturité de Richardson : le niveau 2 est devenu le « RESTful » de fait ; le niveau 3, l'hypermédia, est le seul que Fielding accepte d'appeler REST.

Le malentendu du volet précédent — une « API REST » qui a tout de REST sauf l'hypermédia — n'est pas une impression : il se mesure. Leonard Richardson a proposé en 2008 un modèle de maturité qui classe les services selon ce qu'ils empruntent vraiment au Web ; Martin Fowler l'a popularisé en baptisant son sommet « la gloire de REST ». Quatre niveaux.

Les quatre niveaux

  • Niveau 0 — le tunnel. Un seul point d'entrée, une seule méthode, tout y passe : on poste un appel de fonction sur HTTP, qui ne sert que de transport. C'est le RPC, c'est SOAP. HTTP n'est qu'une enveloppe.
  • Niveau 1 — les ressources. On découpe en URL distinctes, une par chose : /commandes/42, /clients/7. Un progrès, mais on appelle toujours des actions sur ces URL.
  • Niveau 2 — les verbes et les statuts. On emploie les méthodes HTTP selon leur sens — GET lit, POST crée, PUT remplace, DELETE supprime — et les codes de statut pour leur sémantique. C'est, dans l'immense majorité des cas, ce qu'on appelle aujourd'hui « une API REST ». Et c'est là que presque tout le monde s'arrête.
  • Niveau 3 — les contrôles hypermédia. Les réponses portent les liens et les formulaires des actions possibles : HATEOAS. Le client découvre les transitions au lieu de les coder en dur. C'est le seul niveau que Fielding accepte d'appeler REST — et il est rarissime en production.

D'où le verdict, tranché par Fielding lui-même dans un billet resté célèbre : si le moteur de l'état applicatif n'est pas piloté par l'hypertexte, alors ce n'est pas du REST, et ce ne peut pas être une API REST. Au sens strict, une API de niveau 2 n'est pas RESTful : c'est du RPC à belles URL. Elle a gardé l'esthétique — ressources, verbes, JSON — et abandonné la substance.

Le REST du pauvre

Voilà le REST du pauvre : tout ce qui se voit, rien de ce qui coûte. Et ce qu'on a laissé filer, c'est justement le sujet de toute une littérature d'avant la mode des API — celle qui parlait d'hypermédia, de types de média, de client générique. Le prix de cet abandon porte un nom : le couplage hors-bande.

Puisque les réponses ne portent pas les transitions, le client doit les apprendre ailleurs : dans une documentation, un contrat figé. Ce contrat a même son outillage roi, OpenAPI (l'ex-Swagger) : un fichier décrit les routes, les paramètres et les formes de réponse, dont on génère clients et documentation. C'est commode — et c'est l'aveu même du niveau 2 : si le contrat doit vivre dans un document à côté de l'API, c'est qu'il n'est pas dans les réponses. Le client y lit les gabarits d'URL et les grave dans son code ; chacun doit connaître ce contrat à l'avance.

La différence se voit dans une réponse. Au niveau 2, une commande renvoie ses données brutes ; le client doit savoir, par ailleurs, à quelle URL la payer ou l'annuler :

{ "reference": "C-42", "statut": "en attente de paiement" }

Au niveau 3, la même réponse porte ses transitions — le client n'a plus rien à connaître d'avance, il suit ce qu'on lui tend :

{
  "reference": "C-42",
  "statut": "en attente de paiement",
  "_liens": {
    "payer":   { "method": "POST",   "href": "/commandes/C-42/paiement" },
    "annuler": { "method": "DELETE", "href": "/commandes/C-42" }
  }
}

Le premier client connaît l'API par cœur ; le second se laisse guider. Le symptôme le plus visible de l'abandon, c'est le numéro de version dans l'URL, /v1/, /v2/ : l'aveu qu'on ne sait pas faire évoluer l'interface sans casser les clients.

Fielding le formule sans détour : on ne peut pas avoir d'évolutivité si les contrôles des clients sont gravés dans leur conception au moment du déploiement ; ces contrôles doivent s'apprendre à la volée, et c'est ce que permet l'hypermédia. Le versionnage l'illustre par l'absurde : soit on change la version, et tous les composants écrits pour l'ancienne doivent être redéployés ou abandonnés ; soit on n'en change jamais, et elle devient un poids mort que traîne chaque appel.

Quand le niveau 2 suffit — et comment l'appeler

Faut-il pour autant viser le niveau 3 partout ? Non — et c'est l'honnêteté qui manque le plus au débat. Le couplage hors-bande est bon marché quand on maîtrise les deux bouts : si le client et le serveur sont livrés ensemble, par la même équipe, et évoluent de concert, alors un contrat OpenAPI partagé est parfaitement raisonnable, et l'hypermédia n'achèterait qu'une souplesse dont on n'a pas l'usage. Le niveau 2 est souvent le bon choix.

REST n'est d'ailleurs pas la seule réponse au couplage, et il est honnête de le dire. GraphQL et gRPC font un autre pari : plutôt que de découvrir les transitions à la volée, ils misent sur un schéma fortement typé, partagé et outillé (génération de code des deux côtés). C'est un couplage assumé et explicite, taillé pour le cas où l'on maîtrise les deux bouts — l'inverse exact du client générique, mais un choix cohérent quand l'évolutivité ouverte n'est pas l'objectif.

De quoi tirer une grille — la question n'est pas « quel est le plus pur ? » mais « lequel pour quel contexte ? » :

  • Client et serveur d'une même équipe, livrés ensemble → niveau 2 + OpenAPI ; l'hypermédia n'achèterait rien.
  • Plusieurs consommateurs internes, qui évoluent en décalé → niveau 2 solide, hypermédia sur les seules ressources qui changent souvent.
  • API publique, tierce, à longue durée de vie, clients non contrôlés → niveau 3 (hypermédia), ou versionnage assumé et documenté.
  • Sur- ou sous-récupération de données pénible (mobile, écrans hétérogènes) → GraphQL, pour laisser le client composer sa requête.
  • Service-à-service interne, latence et typage critiques → gRPC, contrat typé et binaire.
  • Surface destinée à un agent → niveau 3 / hypermédia — on y vient au dernier volet.

L'erreur n'est donc pas de choisir le niveau 2 ; c'est de l'appeler REST et d'oublier ce qu'on a troqué. Nommer les choses suffit à clarifier : ce n'est pas du REST, c'est du RPC sur HTTP, bien fait. Un excellent niveau 2 vaut mieux qu'un niveau 3 bâclé. Mais quand l'évolutivité compte vraiment — clients tiers, longue durée de vie, couplage à éviter —, l'hypermédia cesse d'être un luxe. Reste à savoir si ce niveau 3 si rare est une utopie d'architecte ou une pratique vivante : il revient, justement, et par le HTML. C'est l'objet du prochain volet.

Laisser un commentaire

Vous devez être connecté pour pouvoir laisser un commentaire.