Enchaînement des requêtes API avec API Gateway

À mesure que le nombre d'API à intégrer augmente, la gestion de la complexité des interactions API devient de plus en plus difficile. En utilisant la API Gateway, nous pouvons créer une séquence d'appels API, ce qui décompose les workflows API en étapes plus petites et plus gérables. Par exemple, sur un site web de commerce en ligne, lorsqu'un client recherche un produit, la plateforme peut envoyer une requête à l'API de recherche de produits, puis envoyer une requête à l'API de détails des produits pour récupérer plus d'informations sur les produits. Dans cet article, nous allons créer un plugin personnalisé pour la Apache APISIX API Gateway afin de gérer les requêtes client qui doivent être appelées en séquence.

Objectifs d'apprentissage

Vous apprendrez les éléments suivants tout au long de l'article :

  • Que sont les requêtes API enchaînées ?
  • Exemple d'appels API séquentiels.
  • Comment construire un plugin personnalisé pipeline-request pour Apache APISIX.
  • Démonstration du plugin pipeline-request.

Pipelining API requests with API Gateway

Qu'est-ce qu'une requête API enchaînée et pourquoi en avons-nous besoin ?

Les requêtes API enchaînées (ou requêtes en pipeline, ou appels API séquentiels) sont une technique utilisée dans le développement de logiciels pour gérer la complexité des interactions API lorsque le logiciel nécessite plusieurs appels API pour accomplir une tâche. Cela ressemble au traitement par lots des requêtes où vous regroupez plusieurs requêtes API en une seule requête et les envoyez au serveur en tant que lot. Bien qu'ils puissent sembler similaires, une requête en pipeline consiste à envoyer une seule requête au serveur qui déclenche une séquence de requêtes API à être exécutées dans un ordre défini. Chaque requête API dans la séquence peut modifier les données de la requête et de la réponse, et la réponse d'une requête API est transmise comme entrée à la requête API suivante dans la séquence. Les requêtes en pipeline peuvent être utiles lorsqu'un client doit exécuter une séquence de requêtes API dépendantes qui doivent être exécutées dans un ordre spécifique.

À chaque étape du pipeline, nous pouvons transformer ou manipuler les données de la réponse avant de les transmettre à l'étape suivante. Cela peut être utile dans des situations où les données doivent être normalisées ou transformées ou filtrer les données sensibles avant d'être renvoyées au client. Cela peut aider à réduire la latence globale. Par exemple, un appel API peut être effectué pendant qu'un autre attend une réponse, réduisant ainsi le temps total nécessaire pour terminer le workflow.

sequential API calls with API Gateway

Plugin personnalisé pipeline-request pour Apache APISIX

Une API gateway peut être l'endroit idéal pour implémenter cette fonctionnalité car elle peut intercepter toutes les requêtes de l'application client et les rediriger vers les destinations prévues. Nous allons utiliser Apache APISIX car c'est une solution API Gateway open-source populaire avec un ensemble de plugins intégrés. Cependant, au moment de la rédaction de cet article, APISIX ne disposait pas de support officiel pour le plugin pipeline-request. En ayant connaissance des capacités de développement de plugins personnalisés d'APISIX, nous avons décidé d'introduire un nouveau plugin qui peut offrir la même fonctionnalité. Il existe un dépôt sur GitHub avec le code source écrit en langage de programmation Lua et une description du plugin pipeline-request.

Avec ce plugin, vous pouvez spécifier une liste d'API en amont qui doivent être appelées en séquence pour gérer une seule requête client. Chaque API en amont peut modifier les données de la requête et de la réponse, et la réponse d'une API en amont est transmise comme entrée à l'API en amont suivante dans le pipeline. Le pipeline peut être défini dans une configuration de Route, et vous pouvez également définir l'ordre des URL API lorsque le pipeline doit les exécuter.

Comprenons l'utilisation de ce plugin avec un exemple. Supposons que vous avez deux API - une qui effectue des requêtes GET /credit_cards pour récupérer les informations de carte de crédit et une autre qui reçoit les données de réponse précédentes dans le corps de la requête POST /filter et filtre ensuite les données sensibles (telles que le numéro de carte de crédit et la date d'expiration) avant de renvoyer la réponse au client. Parce que l'endpoint API de carte de crédit renvoie des informations sensibles qui ne doivent pas être exposées à des parties non autorisées. Le diagramme ci-dessous illustre le flux de données global :

sequential API calls with API Gateway to filter

  1. Lorsqu'un client effectue une requête à l'endpoint API de carte de crédit de l'API Gateway pour récupérer toutes les informations de carte de crédit, l'API Gateway transmet une requête pour récupérer les données de carte de crédit du service backend de carte de crédit.
  2. Si la requête réussit et renvoie des données de carte de crédit, elles sont transmises à l'étape suivante du pipeline qui est le service de sécurité.
  3. Lorsque la réponse filtrée est reçue du service de sécurité, elle renvoie la réponse combinée au client.

Démonstration du plugin pipeline-request

Pour cette démonstration, nous allons utiliser un autre projet de démonstration préparé sur GitHub où vous pouvez trouver tous les exemples de commandes curl utilisés dans ce tutoriel, exécuter APISIX et activer un plugin personnalisé sans configuration supplémentaire avec un fichier Docker compose.yml.

Prérequis

  • Docker est utilisé pour installer etcd et APISIX conteneurisés.
  • curl est utilisé pour envoyer des requêtes à l'API Admin d'APISIX. Vous pouvez également utiliser des outils faciles comme Postman pour interagir avec l'API.

Étape 1 : Installer et exécuter APISIX et etcd

Vous pouvez facilement installer APISIX et etcd en exécutant docker compose up depuis le dossier racine du projet après avoir fork/cloné le projet. Vous remarquerez peut-être qu'il y a un volume ./custom-plugins:/opt/apisix/plugins:ro spécifié dans le fichier docker-compose.yml. Cela monte le répertoire local ./custom-plugins où se trouve notre fichier pipeline-request.lua avec l'implémentation du plugin personnalisé en tant que volume en lecture seule dans le conteneur docker au chemin /opt/apisix/plugins. Cela permet d'ajouter des plugins personnalisés à APISIX pendant l'exécution (Cette configuration n'est applicable que si vous exécutez APISIX avec docker).

Étape 2 : Créer la première Route avec le plugin pipeline-request

Une fois APISIX en cours d'exécution, nous utilisons la commande cURL qui est utilisée pour envoyer une requête HTTP PUT à l'endpoint /routes de l'API Admin d'APISIX pour créer notre première route qui écoute le chemin d'URI /my-credit-cards.

curl -X PUT 'http://127.0.0.1:9180/apisix/admin/routes/1' \
--header 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' \
--header 'Content-Type: application/json' \
--data-raw '{
   "uri":"/my-credit-cards",
   "plugins":{
      "pipeline-request":{
         "nodes":[
            {
               "url":"https://random-data-api.com/api/v2/credit_cards"
            },
            {
               "url":"http://127.0.0.1:9080/filter"
            }
         ]
      }
   }
}'

La partie importante de la configuration est la section "plugins", qui spécifie que le plugin "pipeline-request" doit être utilisé pour cette route API. La configuration du plugin contient un tableau "nodes", qui définit la séquence des requêtes API qui doivent être exécutées dans le pipeline. Vous pouvez y définir une ou plusieurs API. Dans ce cas, le pipeline se compose de deux nœuds : le premier nœud envoie une requête à l'API https://random-data-api.com/api/v2/credit_cards pour récupérer les données de carte de crédit, et le deuxième nœud envoie une requête à une API locale à http://127.0.0.1:9080/filter pour filtrer les données sensibles des informations de carte de crédit. La deuxième API sera simplement une fonction serverless utilisant le plugin serverless-pre-function d'APISIX. Elle agit simplement comme un service backend pour modifier la réponse de la première API.

Étape 3 : Créer la deuxième Route avec le plugin serverless

Ensuite, nous configurons une nouvelle route avec l'ID 2 qui gère les requêtes à l'endpoint /filter dans le pipeline. Elle active également le plugin serverless-pre-function existant d'APISIX où nous spécifions une fonction Lua qui doit être exécutée par le plugin. Cette fonction récupère simplement le corps de la requête de la réponse précédente, remplace le champ du numéro de carte de crédit et laisse le reste de la réponse inchangé. Enfin, elle définit le corps de la réponse actuelle sur le corps de la requête modifié et renvoie une réponse HTTP 200 au client. Vous pouvez modifier ce script pour l'adapter à vos besoins, par exemple en utilisant le corps décodé pour effectuer un traitement ou une validation supplémentaire.

curl -X PUT 'http://127.0.0.1:9180/apisix/admin/routes/2' \
--header 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' \
--header 'Content-Type: application/json' \
--data-raw '
{
  "uri": "/filter",
  "plugins":{
    "serverless-pre-function": {
            "phase": "access",
            "functions": [
                "return function(conf, ctx)
                    local core = require(\"apisix.core\")
                    local cjson = require(\"cjson.safe\")

                    -- Get the request body
                    local body = core.request.get_body()
                    -- Decode the JSON body
                    local decoded_body = cjson.decode(body)

                    -- Hide the credit card number
                    decoded_body.credit_card_number = \"****-****-****-****\"
                    core.response.exit(200, decoded_body);
                end"
            ]
        }
    }
}'

Étape 3 : Tester la configuration

Il est maintenant temps de tester la configuration globale. Avec la commande curl ci-dessous, nous envoyons une requête HTTP GET à l'endpoint http://127.0.0.1:9080/my-credit-cards.

curl http://127.0.0.1:9080/my-credit-cards

Nous avons la route correspondante configurée dans la deuxième étape pour utiliser le plugin pipeline-request avec deux nœuds, cette requête déclenchera le pipeline pour récupérer les informations de carte de crédit à partir de l'endpoint https://random-data-api.com/api/v2/credit_cards, filtrer les données sensibles en utilisant l'endpoint http://127.0.0.1:9080/filter, et renvoyer la réponse modifiée au client. Voir la sortie :

{
   "uid":"a66239cd-960b-4e14-8d3c-a8940cedd907",
   "credit_card_expiry_date":"2025-05-10",
   "credit_card_type":"visa",
   "credit_card_number":"****-****-****-****",
   "id":2248
}

Comme vous pouvez le voir, il remplace le numéro de carte de crédit dans le corps de la requête (en fait, c'est la réponse du premier appel API dans la chaîne) par des astérisques.

Résumé

Jusqu'à présent, nous avons appris que notre plugin personnalisé pipeline-request pour l'API Gateway Apache APISIX nous permet de définir une séquence d'appels API en tant que pipeline dans un ordre spécifique. Nous pouvons également utiliser ce nouveau plugin en combinaison avec ceux existants pour activer l'authentification, la sécurité et d'autres fonctionnalités de l'API Gateway pour nos endpoints API.

Ressources connexes

Share article link