API REST qu’est-ce que c’est?
Dans un monde ou les architectures microservices envahissent nos systèmes d’information, surtout avec l’évolution du Cloud, on entend souvent parler des APIs REST ou RESTful. Tellement apprécié, le terme s’est transformé en symbole de maturité dans les architectures des SI.
Dans cet article je vais aborder les différents aspects d’une API REST et les principaux fragments de son écosystème aujourd’hui.
HISTOIRE
L’acronyme REST (REpresentational State Transfer) a été inventé par Roy Fielding, un scientifique américain qui a beaucoup contribué dans les spécifications du protocole HTTP. Le terme est apparu la première fois dans sa thèse de doctorat sur les styles d’architecture des logiciels en réseaux «Architectural Styles and the Design of Network-based Software Architectures».
DÉFINITION
REST est un style d’architecture pour les systèmes distribués bâti sur des APIs permettants de centraliser des services partagés.
Il est bien évident que les réseaux relient des logiciels technologiquement hétérogènes, ce qui justifie l’utilisation d’un langage commun au niveau des échanges (souvent du JSON ou du XML).
Chose importante, la philosophie REST est plutôt connue sur le Web grâce au protocole HTTP qui valide la majorité de ses contraintes.
LES 6 CONTRAINTES DE «ROY FIELDING»
Pour considérer qu’une API est RESTful, 6 contraintes ont été proposées par Roy Fielding:
- Client-Server – Un mode de communication avec séparation de rôles entre client et serveur.
- Stateless Server – Les requêtes doivent contenir toutes les informations nécessaires au traitement. Il ne doit pas y avoir une notion de session côté serveur. Cette contrainte est indispensable pour rendre une API scalable.
- Cache – La réponse du serveur doit être cacheable côté client.
- Uniform interface – La méthode de communication entre client et serveur doit être uniforme avec des ressources identifiables, représentables et auto-descriptives. Autrement dit, en vocabulaire HTTP, avec une URL et une réponse contenant un body et une entête.
- Layered System – Le système doit permettre le rajout de couches intermédiaires (proxy server, firewall, CDN, etc …).
- Code-on-Demand Architecture (optionnelle) – L’architecture doit permettre d’exécuter du code côté client.
Réellement, beaucoup d’APIs se considérant RESTful ne valident pas la totalité de ces contraintes. C’est ainsi qu’un modèle de maturité a été proposé par Leonard Richardson afin de les classifier.
LE MODELE DE MATURITE DE RICHARDSON
Le modèle de maturité de Richardson définit 4 niveaux de développement dans les APIs REST (de 0 à 3) dont le niveau 3 représente une API totalement RESTful.
La différenciation entre les 4 niveaux peut se baser sur 4 critères:
LES IDENTIFIANTS DE RESSOURCE
REST est une architecture orientée ressources où chaque ressource est accessible via un identifiant unique (URI).
LES VERBES HTTP
Fondé sous le principe KISS (Keep it simple, stupid), REST a su profiter des verbes HTTP pour définir des spécifications d’échange facilement intégrables à tout système.
GET
Permet de récupérer les données d’une ou plusieurs entités dans une ressource. Il est possible de filtrer par des paramètres dans l’url.
curl -X GET https://api.site.fr/vehicule?immat=aa111aa
POST
Permet de rajouter des entités à une ressource. Les données sont envoyées dans le corps de la requête.
Par défaut, une requête POST intègre le format Content-Type:
. Ce format est déconseillé avec les APIs REST car il ne correspond pas aux formats de réponse utilisés (JSON, XML).
curl -H "Content-Type: application/json" -X POST -d '{"immat":"aa111aa", "marque": "peugeot"}' https://api.site.fr/vehicules
PUT
Permet de modifier les données d’une entité dans une ressource.
L’url doit indiquer l’identifiant de l’entité. Si l’identifiant est inexistant, l’entité devrait être créée.
curl -H -X PUT -d '{"immat":"aa111aa", "marque": "peugeot"}' https://api.site.fr/vehicules/1
PATCH (OPTIONNEL)
Permet de modifier en partie les données d’une entité dans une ressource.
Ce verbe ne fait pas partie des opérations de base pour la persistance des données (CRUD) mais pourrait être considéré comme une extension au verbe PUT lui permettant de simplifier les mises à jour partielles.
curl -H -X PATCH -d '{"immat":"aa222aa"}' https://api.site.fr/vehicules/1
DELETE
Permet de supprimer une entité dans une ressource.
curl -H -X DELETE https://api.site.fr/vehicules/1
LES CODES RETOUR HTTP D’API REST
Les codes retours permettent de donner un statut aux réponses renvoyées par l’API.
HATEOAS
Par définition, HATEOAS (Hypermedia As The Engine Of Application State) est une contrainte sur la présence de liens au niveau des ressources pour permettre une navigation exploratoire.
Malgré l’omniprésence de cette contrainte dans le Web (liens hypertexte), elle est rarement intégrée dans les APIs REST car beaucoup considèrent qu’une bonne documentation est suffisante pour mieux explorer une API. D’ailleurs, plusieurs grands noms d’Internet dont Facebook, Twitter et Amazon n’ont pas pris en considération ce niveau 3.
Toutefois, HATEOAS est devenu un terme définissant une API complètement mature.
Ci-dessous un exemple d’une réponse en JSON valide HATEOAS avec les liens self
et list
.
{ "id": 1, "immat": "aa111aa", "marque": "peugeot", "links": [ { "rel": "self", "href": "https://api.site.fr/vehicules/1" }, { "rel": "list", "href": "https://api.site.fr/vehicules " } ] }
Comme vous pouvez le constater, les liens sont au niveau de l’attribut links
. Pour l’instant, il n’y a aucune règle de nomenclature sur les attributs. En revanche, il existe des efforts pour standardiser les principes HATEOAS. JSON-LD et Hydra sont en tête de course pour être adoptés par le W3C.
SÉCURITÉ
D’une manière générale, une API est censée être sécurisée et protégée contre les requêtes anonymes.
En pratique, trois techniques sont principalement utilisées pour sécuriser une API:
- HTTP Basic Authentication
- Oauth
- OpenID
HTTP Basic Authentication
Il s’agit de la solution la plus simple. Consiste à envoyer le login et le mot de passe dans l’entête de chaque requête.
Bien évidemment, il est fortement conseillé d’utiliser le protocole HTTP en mode chiffré (HTTPS) pour ne pas circuler le mot de passe en claire dans les trames réseaux (faille aux attaques de type MITM).
Pour plus de sécurité, surtout si le client de l’API est à l’extérieur de votre réseau, il est préconisé d’utiliser un jeton de sécurité JWT (Json Web Token). Le JWT devrait avoir une durée de vie (TTL) limitée.
Oauth
Oauth est un protocole de délégation d’autorisation nécessitant un serveur tiers comme fournisseur d’accès.
Malgré la complexité de sa mise en place, ce protocole est très apprécié pour sa sécurité.
Il existe deux versions:
- Oauth 1.0 – Il s’agit de la version la plus dure à mettre en place car nécessite un partage de clé entre client et serveur pour le calcul d’une signature (même principe que SSL). Cette version est recommandée pour les APIs sans HTTPS.
- Oauth 2.0 – Cette version est plus aisée à mettre en place car ne dispose pas de calcul de signature. Par contre, en l’occurrence le HTTPS est exigé. Néanmoins, cette version est moins sécurisée que Oauth 1.0.
OpenID
De base, OpendID est un système d’identification en mode SSO. Il permet à un client de se connecter auprès de plusieurs sites sans devoir créer un compte à chaque fois.
Le mode de fonctionnement ressemble à celui de Oauth. Il faut un fournisseur d’identité (OpendID providers) pour établir un lien de confiance entre le client et le serveur. Souvent, le fournisseur d’identité est un grand nom du Web (facebook, twitter, google, …).
D’autre part, cette solution ne permet pas de gérer l’authentification. De ce fait, il existe une deuxième version (OpenID Connect) qui intègre une sous couche Oauth.
VERSIONING
Comme toute chose dans la vie, une API est amenée à bouger dans le temps.
Les modifications au niveau des ressources sont souvent problématiques car nécessitent des mises à jour côté client qui peuvent s’avérer très compliqués, surtout si ce dernier est en dehors du périmètre (partenaire ou application mobile). De ce fait, il est préconisé de ne pas modifier les services mais plutôt d’en créer de nouveaux.
“Versioning an interface is just a « polite » way to kill deployed clients.”
Roy Fielding
En général, il y a trois façons de versioning:
- Via l’URL – Consiste à rajouter le numéro de version dans l’URL de chaque ressource.
- Via l’entête HTTP – S’appuie sur des mécanismes d’identification de version depuis l’entête de la requête (
AcceptHeaderVersioning). - Via les paramètres – Dans ce type de gestion, la version est passée dans les paramètres de la requête.
Même si cela peut paraître confus avec l’une des contraintes du REST (Uniform interface), le versioning via l’URL est la solution la plus adoptée dans les APIs.
DOCUMENTATION
La documentation est un élément central pour faire en sorte que les personnes puissent exploiter une API. Il est important que cette documentation soit rédigée par les développeurs eux-même.
Voici deux solutions pour la mise en oeuvre d’une documentation efficace:
- CARTE – Solution basée sur Jekyll.
- http://apidocjs.com/ – Solution en Javascript (Node.js).
API MANAGEMENT
Comme nous venons de le voir, une API demande beaucoup d’affection (sécurité, versioning, documentation). De plus, de nouveaux besoins ont apparu, comme: le contrôle d’accès par quotas la monétisation de l’utilisation le cache et la scalabilité sur le Cloud.
C’est ainsi que des solutions d’API Management (ou API Gateway) ont commencé à voir le jour afin de répondre à ces besoins. Dans ces solutions, voici quelques unes que je trouve intéressantes:
- Kong– Solution open-source basée sur un système de plugins.
- Ty – Solution open-source facilement intégrable et disponible en version dockerisée.
- https://gravitee.io/ – Solution open-source en Java.
- Zuul – Solution open-source en Java.
- API Umbrella – Solution open-source en Java.