17 Octobre 2017

GraphQL, un complément intéressant à REST pour exposer vos contenus dans Drupal

Commentaires

Le standard REST est de nos jours devenu une norme dans l’élaboration d’APIs pour le web... Graphql propose une autre approche, complémentaire et intéressante pour exposer vos contenus...

Qu’est-ce que GraphQL ?

Le standard REST est de nos jours devenu une norme dans l’élaboration d’APIs pour le web. Elle est simple à comprendre, plus qu’une norme, c’est un ensemble de bonnes pratiques à respecter (ou pas…). Quand on aborde aujourd’hui une interface avec un service tiers, on s’attend à une API REST avec son point d’entrée à interroger via les verbes HTTP GET / POST etc. et ses résultats transmis en JSON.

Cette simplicité et cette omniprésence ne vont pas sans quelques inconvénients. GraphQL est une autre solution qui se propose de résoudre certains écueils de l’architecture REST. Elle n’a pas vocation pour autant à enterrer REST d’après ses promoteurs qui voient les deux approches cohabiter en fonction des besoins. Le temps nous dira si l’une ou l’autre gagnera la bataille.

Plusieurs grosses sociétés (Facebook et Github par exemple) l’utilisent déjà en production. Github propose en supplément de son habituelle API REST, une version GraphQL.

Pourquoi GraphQL ?

Imaginons que nous soyons en présence d’une API nous permettant de récupérer les contenus d’un blog. Nous aurions d’une part une méthode GET /post/{id} qui nous permettra de récupérer la liste des derniers billets du blog ou un billet en particulier. Et d’autre part une méthode GET /comment/{id} pour obtenir les commentaires d’un billet particulier.

Une des demandes est de n’afficher en page d’accueil de notre site que les 3 derniers billets du blog et sur l’affichage détaillé d’un billet, de proposer d’autres articles du même auteur.

Avec un peu de chance l’API peut proposer des paramètres supplémentaires, de type “?limit=3” pour n’obtenir que les 3 derniers ou “?author=xxx” pour filtrer par auteur, mais cela n’est pas obligatoire. Il faut parcourir la documentation si elle existe, bien vérifier la version de l’API en cours, et est-ce author qui a été retenu ou name ? Est-ce que ce paramètre prend un entier ou une chaine de caractères ?

A ce stade, soit l’équipe de développement front-end prend sur elle d’effectuer les traitements “côté client”, soit on reporte cette charge sur celle qui s’occupe des données. Mais est-ce bien à cette dernière de travailler pour répondre à des besoins qui sont essentiellement de l’ordre de l’affichage ? La base de données qui stocke les billets du blog est bien structurée, on sait très bien que chaque article dispose d’un auteur, d’un titre et d’un certain nombre de commentaires, quelque part ce serait une redite.

Puis on vous demande finalement de n’afficher que les titres en page d’accueil. A moins de disposer d’une méthode GET /post_title (je souffre déjà en l’écrivant), il va vous falloir là aussi tout récupérer pour ne garder que les titres.

Ce n’est pas la mer à boire certes, nous le faisons au quotidien et même si l’on demande au navigateur de récupérer 100ko de données pour n’en afficher qu’un dixième, on ne le sent pas avec nos connexions 4G et notre couverture réseau impeccable (et puis on ne paye pas la bande passante alors...) Bref, on le fait mais quand on y regarde de plus près ça n’est pas l’idéal.

Le lendemain, toujours en page d’accueil, on vous presse d’afficher le nombre de commentaires à la suite de chaque billet. Là aussi, à moins qu’une âme charitable ait pensé à rajouter l’information dans la méthode GET “/post”, il vous faudra pour chaque titre de billet récupéré, effectuer une requête HTTP supplémentaire pour obtenir ses commentaires et en déduire le nombre total. C’est également une pratique courante, mais qui peut s’avérer problématique en cas de mauvaise connexion, etc.

Et si nous renommons un champs dans notre API ou en rajoutons un nouveau ? Avec une architecture, cela implique de maintenir 2 versions d’une même API pour éviter les catastrophes auprès des anciens consommateurs de votre v1.

L’objectif de GraphQL est clairement d’apporter une solution à toutes ces situations dans le meilleur des cas bancales.

GraphQL est un langage de requêtes (le QL comme sans SQL) initialement développé par Facebook (quand on veut garder le monopole auprès des pays émergents et sur terminaux mobiles, chaque requête et chaque kilo-octets comptent).

GraphQL offre une meilleure séparation des responsabilités entre les logiques d’affichage et celles du métier.

GraphQL se positionne entre votre client (le navigateur, pas celui qui vous paye) qui a besoin de certaines informations bien précises et votre serveur qui doit les lui fournir.

GraphQL permet :

  • De n’obtenir que les informations demandées par la requête (et uniquement celles-ci) ;
  • De faire des requêtes imbriquées dans d’autres requêtes (comme obtenir d’une seule traite, les billets et les commentaires qui leurs sont associés) ;
  • D’avoir un typage fort des données, là où une API REST ne vous offrait aucune garantie. Vous pouvez savoir avec exactitude que tel paramètre devra être un entier et pas un booléen ;
  • D’avoir une documentation “automatique” qui reflète la structure même des données qu’il est possible d’obtenir. GraphQL le prévoit et il y a des outils qui permettent en temps réel de savoir la structure d’un résultat pour choisir ce que l’on voudra afficher ou pas, les relations des entités entre elles, etc.
  • De ne pas être dépendant d’une version ou d’une autre. Puisque l’on obtient ce que l’on a demandé… Quand un champ existant n’est plus utilisé, on peut le déprécier pour avertir l’équipe technique, mais l’information reste disponible pour la durée souhaitée.

GraphQL, comment ça marche ?

Avec GraphQL il n’y a plus qu’un seul endpoint sur lequel nous allons faire toutes nos requête. Par exemple :

{
      author {
        name
        posts {
          title
          comments {
            comment
          }
        }
      }
    }

Et la réponse sera (notez l’effet “miroir”) :

{
      "data": {
        "author": {
          "name": "C. Dugué",
          "posts": [
            {
              "title": "Drupal 8.4 est là !",
              "comments": [
                {
                  "comment": "Ça fait plaisir !"
                }
              ]
            },
            {
              "title": "Nouveau site Bluedrop",
              "comments": [
                {
                  "comment": "C'est pas trop tôt ! ;)"
                }
              ]
            }
          ]
        }
      }
    }

En une seule requête, nous avons reçu en retour les informations structurées comme nous les avions demandées (et uniquement ces dernières, rien de plus, rien de moins).

Avec REST nous aurions du faire une requête pour récupérer l’id de l’auteur, puis une seconde pour récupérer les posts ayant l’id de cet auteur, puis pour chaque post, d’autres requêtes pour récupérer les bons commentaires…

De même voici une requête permettant de récupérer le nombre des commentaires avec une pagination (source) :

{
  hero {
    name
    friendsConnection(first:2 after:"Y3Vyc29yMQ==") {
      totalCount
      edges {
        node {
          name
        }
        cursor
      }
      pageInfo {
        endCursor
        hasNextPage
      }
    }
  }
}

Résultat :

{
  "data": {
    "hero": {
      "name": "R2-D2",
      "friendsConnection": {
        "totalCount": 3,
        "edges": [
          {
            "node": {
              "name": "Han Solo"
            },
            "cursor": "Y3Vyc29yMg=="
          },
          {
            "node": {
              "name": "Leia Organa"
            },
            "cursor": "Y3Vyc29yMw=="
          }
        ],
        "pageInfo": {
          "endCursor": "Y3Vyc29yMw==",
          "hasNextPage": false
        }
      }
    }
  }
}

Et Drupal dans tout ça ?

Il existe un module GraphQL pour Drupal permettant d’exposer les contenus du CMS avec le endpoint qui va bien.

Pour l’affichage, il y a plusieurs outils développés par Facebook : Appolo notamment qui offre les librairies nécessaire (React, Angular, Swift) pour les requêtes et l’affichage côté client. Il existe tout de même une adaptation pour VueJS : https://github.com/Akryum/vue-apollo.

On oublie REST ?

Non pas pour le moment et peut-être pas du tout. Encore une fois les 2 technologies sont faites pour cohabiter. Une des limitations de GraphQL actuellement réside dans la gestion du cache, beaucoup plus complexe à mettre en place qu’avec REST. Pour des cas simples et avec beaucoup de trafic, le système actuel a encore de beaux jours devant lui.

Ludovic Coullet - @lcoullet

Site officiel : http://graphql.org/

Articles sources :