Beaucoup de concepteurs de Web APIs présentent leurs APIs comme étant RESTful. Pourtant celles-ci ont souvent peu à voir avec REST. Que doit-il être fait pour que l’API d’un Web service soit réellement RESTful ?
D’après la thèse de Roy Fielding, Architectural Styles and the Design of Network-based Software Architectures, REST est le style d’architecture sur lequel est construit le WWW. Ce style correspond à un ensemble de principes et un ensemble de contraintes qui soutiennent ces principes. Sans essayer d’être exhaustif, nous allons énumérer certains principes, significatifs dans le cadre de cette discussion, et en donner de rapides descriptions :
- Identification des ressources : chaque ressource sur le web est identifiée de façon unique par un ID, qui est une URI.
- Liens : un client navigue de ressource en ressource via hypermédia.
- Représentations multiples des ressources : un client ne traite pas directement avec la ressource mais à travers une représentation de cette ressource. Il peut exister de multiples représentations d’une ressource.
D’autres principes peuvent être mentionnés : l’utilisation de communications serveur-client sans état, de méthodes standardisées et de messages auto-descriptifs. Depuis la publication de Roy Fielding, les Web APIs ont proliféré sur Internet et beaucoup de leurs concepteurs les ont qualifiées de RESTful, c’est-à-dire conforme aux principes REST.
Bien que ces APIs soient tout à fait fonctionnelles et que celles-ci ont souvent remplacé avec succès les anciennes solutions WS-*, la question est : sont-elles réellement RESTful ou le terme est-il dévoyé et utilisé comme un buzzword ? Tout manuel de construction d’APIs RESTful suggère généralement de suivre un ensemble de règles, dont : définir des ressources (entités), leur donner des noms, utiliser le pluriel, créer des URIs qui suggèrent les relations entre entités, éviter les liens de profondeur, etc.
Ainsi, une requête/réponse typique sur une telle API ressemble à cela :
Request
GET /books/10
Response
200 OK
{ "book":{ "id":"10", "title": "some_title", "author": "some_author" } }
Bien que de telles APIs aient appliqué certains principes REST, comme l’identification de chaque ressource par un ID, l’utilisation d’hyperliens, la proposition de multiples représentations des ressources (JSON, XML, …), celles-ci n’obéissent pas à tous les principes de REST. On entend parler alors de «REST pragmatique», ce qui a pour effet de répandre de multiples interprétations de REST. Roy Fielding a exprimé sa frustration au sujet d’implémentations d’APIs RESTful il y a plusieurs années, informant à cette occasion les concepteurs d’APIs que quelques règles devaient être respectées pour qu’une API puisse être qualifiée de RESTful, règles que nous rappelons brièvement ici :
- Une API REST ne devrait pas être dépendante d’un protocole de communication.
- Une API REST ne devrait pas apporter de modification aux protocoles de communication.
- Les efforts consacrés aux aspects descriptifs d’une API REST devraient porter le plus souvent possible sur la définition de media types utilisés pour représenter des ressources et piloter l’état de l’application.
- Une API REST ne doit pas fixer de noms pour les ressources et les hiérarchies (ce qui constituerait un couplage évident entre les clients et le serveur).
- Une API REST ne devrait pas exposer de ressource “typée” significative au client.
- Il devrait être possible d’accéder à une API REST sans aucune autre connaissance a priori que l’URI initiale (bookmark).
Concernant la dernière règle, beaucoup d’APIs actuelles n’ont pas de bookmark initial auquel un client peut accéder, suivi d’une façon de fournir avec chaque réponse les liens additionnels ou les templates pour créer ces liens permettant d’accéder aux diverses ressources que le web service a à offrir. Généralement, une documentation externe est mise à la disposition des développeurs pour leur permettre de construire les liens. Si, comme le dit Roy, ceci n’est pas conforme à la façon RESTful de travailler avec les hyperliens, alors comment faut-il faire ?
Stefan Tilkov qui s’autoproclame chef RESTafarien d’innoQ, a suggéré lors de la conférence GOTO pendant sa session REST: I don't Think it Means What You Think it Does (à la 35m 26s de cette vidéo) l’utilisation d’un service document, qui serait la page d’accueil d’un web service. Le client réclamerait cette page d’accueil, le bookmark du service, et recevrait une réponse contenant les ressources disponibles, les opérations possibles à exécuter sur ces ressources et les liens relatifs à utiliser pour y accéder. L’exemple ci-dessous donne l’illustration pour un service de gestion de commandes :
<?xml version="1.0" encoding="UTF-8"?> <serviceDescription xml:base="http://om.example.com"> <link rel="all" href="/orders/" /> <link rel="received" href="/orders/received/" /> <link rel="accepted" href="/orders/accepted/" /> <link rel="rejected" href="/orders/rejected/" /> <link rel="cancelled" href="/orders/cancelled/" /> <link rel="fulfilled" href="http://om.archive.com/orders/" /> <link rel="cancellations" href="/cancellations/" /> <link rel="reports" href="/reports/" /> </serviceDescription>
{ "serviceDescription" : { "base": ", "links": [ { "rel": "all", "href": "/orders/" }, { "rel": "received", "href": "/orders/received/" }, { "rel": "accepted", "href": "/orders/accepted/" }, { "rel": "rejected", "href": "/orders/rejected/" }, { "rel": "cancelled", "href": "/orders/cancelled/" }, { "rel": "fulfilled", "href": "/orders/fulfilled/" }, { "rel": "cancellations", "href": "/cancellations/" }, { "rel": "reports", "href": "/reports/" } ] } }
Bien que cette approche puisse sembler compliquer les choses en introduisant un niveau d’indirection pour la construction des hyperliens, le bénéfice se trouve dans le découplage entre le client et le serveur. Le client n’a plus besoin d’écrire les liens en dur ou à les construire avec une documentation externe, il les récupère du serveur. Le serveur peut changer les liens à tout moment, introduire ou retirer des opérations sur les ressources sans craindre de casser des clients. En fait, d’après Stefen, c’est exactement ce que font certaines entreprises : elles jouent intentionnellement avec les liens pour voir quels clients cassent, afin de voir où les principes REST ne sont pas respectés.
De plus, les réponses d’un serveur devraient inclure des liens de transition d’état. Quand le client opère sur une ressource, la réponse peut contenir des liens vers d’autres opérations qui correspondent aux transitions. Pour les APIs actuelles, les URLs sont devenues les APIs, réduisant REST à un ensemble de patterns d’URIs et des méthodes HTTP comme GET, PUT, POST, DELETE. Pendant cette même session, Stefen Tilkov a demandé à l’audience si les URIs suivantes étaient RESTful (vidéo à 17m 16s) :
http://example.com/customers/format?drive=c
http://example.com/customers/getDetails?id=13
http://example.com/customers/delete?id=13
http://example.com/customers/13
http://example.com/customers/13/edit
Les réponses ont été variées : certains ont considéré certaines d’entre elles comme étant RESTful, d’autres pas. Ceci illustre la confusion autour de REST. Pour Stefen, ce qui est dans une URI n’est pas important car de la perspective de REST, une URI n’est qu’une chaîne de caractères, peu importe ce qu’elle contient. Il n’y a pas de contrainte sur les URIs pour qu’elles soient RESTful. Ce qui compte est le contexte dans lequel les URIs sont utilisées.
Une autre problématique mentionnée par Stefen Tilkov est le versionning des APIs dans les URIs. C’est ce que font beaucoup de créateurs d’APIs, comme le montrent ces exemples, tirés de leurs sites web respectifs :
Swagger word API : http://api.wordnik.com:80/v4/word.json/home
Apigee Edge API : https://api.enterprise.apigee.com/v1/organizations
SauceLabs : https://saucelabs.com/rest/v1/:username/activity
Stefen explique que cela arrive parce que "l’URI est l’expression de l’API" et questionne : "que se passe-t-il lorsque quelqu’un change l’API ?". Il considère qu’une API pourrait inclure un numéro de version si elle réfère à une certaine version de la donnée ou d’un document, mais on ne devrait pas lier une API à des URIs pointant vers des ressources car cela introduit un couplage entre le client et le serveur.
Stefen a fourni d’autres recommandations :
- Utiliser les contrôles hypermedia avancés, comme les formulaires, même pour les communications machine à machine.
- Utiliser des media types différents pour les différents types de ressources.
- Créer de nouvelles ressources si le besoin apparaît.
- Réserver de l’espace pour les liens.
Il est évident que de nombreuses APIs ne sont pas RESTful. Rien n’empêche les entreprises de développer de telles APIs, et cela leur a souvent plutôt réussi. Ce qui est plus difficile à comprendre, c’est pourquoi s’attacher à les qualifier de RESTful ? Un autre terme pourrait être utilisé. Web API pourrait suffire.
Reste à voir l’option qui l’emportera, une des deux tendances va-t-elle s’imposer ou est-ce que l’on restera sur une coexistence entre REST et les web API aspirantes RESTful ? Lors d’une discussion avec InfoQ, Stefen Tilkov a dit qu’il avait confiance dans le fait que REST "avait plus que des avantages théoriques et que lors des quelques décennies passées, l’approche web avait toujours gagné". En même temps, les Web APIs non réellement RESTful ont fleuri sur le web. L’index ProgrammableWeb contient actuellement 12 999 API, dont 6 000 catégorisées "RESTful".
Au sujet de l’Auteur
Abel Avram a participé à de nombreuses activités éditoriales pour InfoQ depuis 2008, notamment à l’écriture de news au sujet du développement Mobile, HTML, .Net, Cloud Computing, architecture d’entreprise. Si vous souhaitez proposer des idées de news ou d’articles, contactez-le à abel [at] infoq.com.