Concevoir une API

On passe aux choses sérieuses… Dans cet article, nous allons parler des composants d'une API en en créant une nous-mêmes. Par l'ami Brian Cooksey, le roi de la pizza pepperoni.


Par

C'est déjà le cinquième article de cette série (1) et nous arrivons maintenant à un tournant dans notre aventure au royaume des API. Nous avons couvert les fondamentaux, et nous sommes prêts à voir comment les concepts précédents peuvent être combinés pour créer une API. Dans cet article, nous allons parler des composants d'une API en en créant une nous-mêmes.

Organiser les données

National Geographic a estimé qu'en 2011 les américains ont fait 80 milliards de photos. Avec une quantité aussi colossale de clichés et de photographes, vous pouvez imaginer les différences de classification de ces photos sur les ordinateurs de leurs auteurs. Certains préfèrent tout ranger dans un seul dossier, d'autres les classent méticuleusement par année, mois, événement...

Il en va de même avec les entreprises lorsqu'elles créent leurs API. Comme nous l'avons déjà vu, l'objectif d'une API est de faciliter la communication entre un ordinateur et les données de l'entreprise. Chaque entreprise choisit la meilleure manière de structurer ses API, en fonction de la situation particulière et des bonnes pratiques de son secteur. Certaines décideront de n'avoir qu'une URL pour l'ensemble des données, que l'on pourra trier (un peu comme si nous n'avions qu'un seul dossier pour toutes nos photos), d'autres assigneront à chaque donnée une URL, les données étant organisées hiérarchiquement (comme des dossiers et sous-dossiers de photos).

Choisir un style d'architecture

Dans les discussions à propos d'API, vous entendez parler de “soap” et de “rest” et vous vous demandez peut-être si les développeurs sont en train de travailler ou de parler de leurs prochaines vacances. En fait il ne parlent ni de savon (soap) ni de repos (rest), mais des deux architectures les plus communes pour les API du web. SOAP est basé sur XML et comporte des structures standardisées de requêtes et réponses. REST (Representational State Transfer) est une approche plus ouverte qui fournit tout un tas de conventions mais laisse une grande liberté de décision au concepteur de l'API.

Tout au long de ces articles, vous avez peut-être remarqué que j'ai un penchant pour les API REST. Ma préférence est largement due à la popularité croissante de REST auprès la communauté.

Notre première ressource

Dans notre deuxième article, nous avons parlé un peu de ressources. Vous vous rappelez que dans les API, les ressources sont l'équivalent des noms (client, pizza,…), ce sont les choses avec lesquelles nous voulons que le monde puisse interagir.

Pour nous faire une idée de la façon dont on peut concevoir une API, faisons-nous la main avec notre pizzeria, et pour commencer : comment créer une commande de pizza ?

Pour que le client puisse parler pizza avec nous, il y a plusieurs choses à faire :

  1. Décider quelles ressources seront disponibles.
  2. Assigner des URL à ces ressources.
  3. Déterminer quelles actions le client sera autorisé à exécuter sur ces ressources.
  4. Savoir quelles données sont requises pour chacune de ces actions et quel doit être leur format.

Notre première tâche est de choisir les ressources, et cela peut s'avérer complexe. Une bonne façon d'approcher le problème est de suivre un processus d'interaction typique : dans notre pizzeria, nous avons probablement un menu, et sur ce menu des pizzas. Quand un consommateur veut une pizza, il passe une commande. Dans ce contexte, menu, pizza, consommateur et commande nous paraissent de bons candidats à l'appellation ressource. Commençons avec la commande.

L'étape suivante est d'assigner des URL aux ressources. Les possibilités sont nombreuses, mais heureusement les conventions REST nous aident. Dans une API REST typique, une ressource aura deux patterns d'URL. Le premier est le pluriel de la ressource, par exemple /commandes . Le deuxième est constitué de ce pluriel, suivi de l'identifiant unique correspondant à une ressource particulière, par exemple /commandes/<id_commande> , dans lequel <id_commande> est l'identifiant unique de cette commande. Ces deux patterns forment le premier endpoint (point final) supporté par notre API. On l'appelle endpoint parce qu'il se situe à la fin de l'URL, comme dans http://exemple.com/<endpoint_est_ici>.

Maintenant que nous avons choisi notre ressource et que nous lui avons assigné des URL, il nous faut déterminer quelles actions le client pourra accomplir. Si nous suivons les conventions REST, nous disons que l'endpoint pluriel (/commandes) sert à lister les commandes existantes et à en créer de nouvelles. Le pluriel combiné avec un identifiant unique en endpoint (/commandes/<id_commande>) sert à récupérer, mettre à jour ou annuler une commande particulière. Le client indique au serveur les actions à accomplir en passant le verbe HTTP approprié (GET, POST, PUT ou DELETE) dans la requête.

Notre API ressemble à ceci :

Verbe HTTP  Endpoint     Action

GET        /commandes    Liste les commandes
POST       /commandes    Passe une commande
GET        /commandes/1  Détails Cde 1 
GET        /commandes/2  Détails Cde 2
PUT        /commandes/1  Modifie Cde 1
DELETE     /commandes/1  Annule Cde 1

Maintenant que nous avons mis un peu de matière autour de nos endpoints, la dernière étape consiste à déterminer quelles données seront échangées entre le client et le serveur. Si nous reprenons notre exemple passé, nous pouvons dire qu'une commande doit intégrer le type de pâte et la garniture. Nous devons également choisir un format de données utilisables par le client et le serveur pour transmettre ces informations dans un sens comme dans l'autre. XML et JSON sont de bonnes options, pour une question de lisibilité je choisirai ici JSON.

Au point où nous sommes parvenus, vous pouvez vous donner une petite tape sur l'épaule : nous avons conçu une API fonctionnelle ! Voici à quoi ressemble une interaction entre le client et le serveur lorsqu'on utilise notre API :


post /commandes détail de la commande

réponse 201 créé

Put /commandes modification de la commande

réponse 200 OK

Figure 1 - Exemple d'interaction client/serveur avec notre API.


Lier les ressources entre elles

Notre API Pizzeria marche d'enfer, les commandes tombent comme s'il en pleuvait. En fait, ça marche tellement bien que nous décidons de tracer les commandes pour évaluer la fidélité clients. Pour cela, rien de plus facile, il suffit d'ajouter une nouvelle ressource consommateur.

Tout comme nos commandes, la ressource consommateur a besoin d'endpoints. Nous suivons les conventions, consommateurs et consommateurs/<id> sont parfaits. Passons sur les détails, nous déterminons quelles actions ont un sens pour chaque endpoint et quelles données représentent un consommateur, et nous arrivons maintenant à une question intéressante : Comment associer les commandes et les consommateurs ?

Les praticiens REST sont partagés sur la manière de résoudre le problème de l'association des ressources. Pour certains, la hiérarchie doit s'étendre, en donnant par exemple un endpoint /consommateurs/5/commandes à toutes les commandes du consommateur n°5 et /consommateurs/5/commandes/3 à la 3ème commande du consommateur n°5. Pour d'autres, il est préférable de garder les choses à plat, en incluant les détails associés dans les données de la ressource. Si l'on suit ce paradigme, la création d'une commande requiert qu'un champ id_consommateur soit envoyé avec les détails de la commande. Les deux solutions sont utilisées par les API REST et il est bon de les connaître toutes les deux.

Figure 2 - Deux façons de gérer les données associées.


Rechercher des données

À mesure que la quantité de données s'accroît, l'utilisation des endpoints listant toutes les ressources devient malcommode. Imaginez si notre pizzeria avait déjà livré 3 millions de pizzas et que nous cherchions à savoir combien étaient des Regina… Envoyer une requête GET à /commandes et recevoir les 3 millions de commandes ne nous aiderait pas beaucoup. Heureusement, REST propose une façon astucieuse de faire des recherches à travers les données.

Les URL ont une composante que nous n'avons pas encore mentionnée, ce sont des chaînes d'interrogation (query string). Ce sont de petits textes qui se situent à la fin d'une URL pour faire passer quelque chose à l'API. Par exemple ici, tout ce qui est après le point d'interrogation est une chaîne d'interrogation : http://exemple.com/commandes?key=value.

Les API REST utilisent les chaînes d'interrogation pour définir les détails d'une recherche. Ces détails sont appelés les paramètres de la recherche. C'est l'API qui dicte les paramètres qu'elle acceptera, et on doit utiliser leur nom exact pour effectuer la recherche. Notre API pizzeria pourrait autoriser le client à faire une recherche par garniture de commandes en utilisant cette URL : http://exemple.com/commandes?garniture=pepperoni. Le client peut inclure plusieurs paramètres dans sa recherche, qu'il liste les uns après les autres, séparés par une esperluette (&), par exemple : http://exemple.com/commandes?garniture=pepperoni&pate=fine.

On peut également utiliser les chaînes d'interrogation pour limiter le nombre de données retournées à chaque requête. Bien souvent les API sépareront les résultats en groupes de 100 ou 500 réponses et retourneront un groupe à la fois, un procédé appelé pagination. Afin de permettre au client d'utiliser cette pagination des données, l'API supporte des paramètres de recherche permettant au client de spécifier la page qu'il souhaite. Dans notre API pizza, nous permettons au client de spécifier deux paramètres : page et taille. Si le client fait la requête GET/commandes?page=2&taille=200, nous savons qu'il veut la deuxième page de résultats, avec 200 résultats par page, donc les commandes 201 à 400.

Récapitulation

Dans cet article, nous avons vu comment concevoir une API REST. Nous avons montré les fonctions de base que supporte une API et la façon d'organiser les données de façon à ce qu'elles soient facilement consommées par un ordinateur.

Les termes-clés que nous avons appris :

SOAP : une architecture API connue pour ses formats de messages standardisés.
REST : une architecture centrée sur la manipulation des ressources.
Ressource : terme API désignant un nom, tel que consommateur ou commande.
Endpoint : une URL qui fait partie d'une API. Avec REST, chaque ressource à son propre endpoint.
Chaîne d'interrogation : une portion d'URL utilisée pour passer des données au serveur.
Paramètres de recherche : une paire clé-valeur (key-value) présente dans la chaîne d'interrogation (garniture=fromage).
Pagination : procédé consistant à présenter les résultats d'une requête en lots exploitables.

TRAVAIL À LA MAISON
Sous la rubrique "Homework", située à la fin de l'article original, vous trouverez quelques applications pratiques avec les API d'Instagram, Facebook et Twitter.

POUR S'AMUSER
Quelques sites pour commencer à jouer avec les API :

  • Marvel : retrouvez les héros des Marvel Comics (Spider Man, Hulk…) avec l'API Marvel
  • Music Graph API, pour retrouver des artistes, des albums, des morceaux

Dans le prochain article, nous verrons comment le client réagit aux changements intervenant sur le serveur en temps réel.

Lire l'article suivant.


Liste des articles parus :   ↩︎


original paru le dans Zapier.com.

Sur l'auteur : travaille chez Zapier.com, vous pouvez le suivre sur Twitter ainsi que Zapier.

Traduit avec l'aimable permission de Zapier et de l'auteur.
Copyright Zapier © 2014.