GraphQL: Une API qui ne parle pas pour rien dire
- Publié:
Pour les non développeurs
GraphQL est une façon de requêter des données via une interface web de type API.
Cette méthode a été ouverte au public par Facebook en 2015 (de façon Open Source) et est de plus en plus utilisée aujourd’hui notamment en dévelopement web. Elle offre la possibilité de définir de façon exacte les données échangeables, de demander exactement celles dont on a besoin et enfin de recevoir exactement ce qu’on a demandé. Cette méthode est donc plus flexible et évite de faire des transformations a posteriori.
Pour les développeurs
1. Pourquoi un nouveau protocole d'API web ?
GraphQL est une spécification open source publiée par Facebook en 2015 qui permet de requêter des données grâce au protocole http sur une interface API.
“ Demande ce que tu veux et obtient exactement ça. “
GraphQL n’utilise qu’un URL (ou endpoint) pour requêter, alors qu'avec une API REST (couramment utilisée) on se retrouve souvent avec un grand nombre d’URLs différentes qui renvoient des données très diverses autant sur le format que le contenu.
Il permet de créer un schéma pour décrire les types et le format des données. Ceci offre la possibilité de requêter exactement la structure de données voulue et de recevoir exactement ce qu’on demande, contrairement aux API REST qui ne permet pas (ou peu) de personnaliser les requêtes et avec lesquelles on peut avoir un gros volume de données en retour qu’il faut ensuite transformer et filtrer avant de pouvoir l’utiliser. En développement web il est aujourd'hui de plus en plus courant que ce soit le code exécuté sur le navigateur (En Front-End avec du javascript par exemple) qui demande à une API les données à afficher à l’utilisateur. GraphQL apporte donc dans ce cas plus de flexibilité et moins de mise en forme à faire. Son utilisation facilite également les discussions entre les équipes de développeurs Frontend et Backend car le Front a le schéma et requête ce dont il a besoin sans demander à développer des requêtes spécifiques comme on le voit avec les API REST.
Avec GraphQL, on modélise notre logique Business comme un graph. Il permet de modéliser notre donnée de façon naturelle en lien avec l'utilisation qu'il va en être faite. On définit dans le schéma différents types de noeuds et on les relie entre eux.
Ce type d’interface n’a pas de version, les évolutions sont plus simples et flexibles car il suffit de faire évoluer le schéma de données. De fait ça encourage les développeurs à n’implémenter que ce dont ils ont besoin. Le but du schéma et de faire retranscrire la logique métier qui sera utilisée par la personne qui demande la donnée au lieu de copier le schéma présent en base de données. Elle offre une facilité d’interopérabilité et permet plus facilement de changer de service utilisateur sans changer tout le Backend.
2. Comment ça marche ?
Différentes opérations sont permises: lire (via le type « Query »), écrire (avec une « Mutation ») et s’inscrire à des flux de données (opération de type « Subscription »).
- La lecture se fait sur un URL sur lequel on demande les champs dont on a besoin. On peut y ajouter également des paramètres pour filtrer
- La modification se fait sur le même URL avec une requête http "GET" donnant les éléments à modifier. Ceci va à l’encontre des conventions http qui poussent à utiliser la méthode http "UPDATE" pour ces cas de figure. Cette requête renvoie un objet.
- Les abonnements (ou Subscription) permettent de recevoir une notification quand la donnée a été modifiée ou qu’un évènement est survenu. Par exemple quand un nouvel utilisateur a été créé.
Les données sont définies et décrites par un schéma. Ce système est typé, avec une sémantique et une validation des données requêtées et renvoyées grâce au schéma. Il définit tous les champs, types et tout ce qui peut être demandé. De plus le schéma est implémenté dans le langage GraphQL ce qui le rend indépendant du langage utilisé coté serveur GraphQL. Les types permis pour les champs sont larges :
- Int: Un nombre entier (integer) 32‐bit.
- Float: Un nombre décimal à 2 décimales.
- String: Une suite de caractères de format UTF‐8.
- Boolean: true ou false.
- ID
- Scalar: un scalaire
- List: une liste
La Query définie précédemment représente toutes les entrées possibles dans l’API. Pour répondre les bonnes données on définit des « resolvers ».
Les resolvers sont des fonctions qui ‘résolvent’ les valeurs pour les différents champs définis dans le schéma. Leur rôle est de renvoyer la donnée requêtée lors d’une « Query », en se connectant par exemple à une base de données ou un fichier de type xls, csv, json .. etc . Ils peuvent être synchrones ou asynchrones selon s'il faut attendre une autre action asynchrone (comme par exemple une réponse d’une requête en base de données).
Ils prennent 4 arguments :
- root : est le résultat récupéré à la sortie du parent
- args : arguments donnés pour la requête. Par exemple un filtre ou une façon de trier le résultat.
- context : valeur donnée à tous les resolvers. Il permet d’avoir accès à une base de données par exemple « context.db.find() »
- info
Le serveur GraphQL se base sur le schéma et les resolvers pour éxécuter les Queries/Mutations/Subscriptions et par conséquent les données demandées.
Il répond sous le même format que la Query mais en JSON.
Par exemple la requête :
répond :
Outil de debug «GraphiQL » : Cet outil permet de créer une documentation à partir du schéma et d'explorer les données de l'API. C'est équivalente à Postman qui est couramment utilisé avec REST. Il possède également l’autocomplétion pour aider à l’utilisation.
Authentification : il existe des règles et directives @AUTH sur les champs mais j’avoue que la mise en œuvre a été un peu laborieuse car elle dépend de l’avancement des librairies de chaque langage. Personnellement en Python ce n’était pas pris en compte et mal documenté donc j’ai dû m’adapter et contourner avec des tokens dans les requêtes HTTP sans utiliser la spécification GraphQL.
Les serveurs GraphQL peuvent être développés en plusieurs langages tels que Javascript, Python, Java, Go, Ruby… Ceci est rendu possible par le développement d’un large choix de librairies et packages par la communauté.
3. Application : GraphQL en Python
Il y a 4 principaux packages à date (Septembre 2020). Ceux ci implémentent avec plus ou moins de fidélité la spécification définie par Facebook. Il y en a qui sont plus ou moins flexibles mais la logique reste la même avec la définition d'un schéma de données et de resolvers.
- Graphene (6k ⭐ sur Github):
C'est le package le plus utilisé. Il est très haut niveau et facilite les interconnexions entre les technos de serveur (comme Flask et Django) et celles de Base de données (avec SQLAlchemy). Il prend en compte Python2 (qui n'est plus maintenu) et Python3. Le schéma de données est défini en python et mélangé avec les resolvers dans des classes. Il y a eu des rumeurs comme quoi le projet n'allait plus être maintenu par ses créateurs. Let's see... - Ariadne (1k ⭐ sur Github):
Il est plus bas niveau et a une approche schéma-first plus proche de la philosophie du protocole GraphQL. Le schéma est d'ailleurs au format définit par la spécification. Il est compatible Python3.5 et les versions suivantes. Il est beaucoup plus récent et progresse trés vite. Il supporte les resolvers asynchrones. - Tartiflette( 650 ⭐ sur Github):
Sa promesse est d'aller plus loin que Graphene avec une meilleure expérience utilisateur et de façon 100% open source. Il est compatible avec Python3.6 et plus récentes. - Strawberry (639 ⭐ sur Github):
Ce package évolue également trés rapidement mais ne bénéficie pas encore d'une large communauté.
Avis perso :
J'ai fait le choix d'utiliser Ariadne car il est plus bas niveau et me laisse bien séparer mon serveur web Flask de ma logique GraphQL. Ariadne n'était pas le package avec la plus grosse communauté sur stackoverflow ou Github, j'ai dû faire preuve d'imagination pour déboguer... Il me permet de définir un fichier schéma avec mon système typé exactement comme détaillé dans la specification de GraphQL.
Coté Front end je n'ai eu aucun soucis en utilisant Apollo pour requêter (React, Vue…) mais ce peut être fait avec JQuery ou les outils habituels permettant de faire des requêtes sur une API web.
Merci de votre lecture et n'hésitez pas à m'envoyer vos commentaires si vous avez eu une expérience avec GraphQL ou si vous voulez en savoir plus !
Florian