API-Anfragen mit API Gateway verketten

Bobur Umurzokov

Bobur Umurzokov

May 23, 2023

Technology

Da die Anzahl der APIs, die integriert werden müssen, zunimmt, wird die Verwaltung der Komplexität von API-Interaktionen immer schwieriger. Durch die Verwendung des API-Gateways können wir eine Abfolge von API-Aufrufen erstellen, die die API-Workflows in kleinere, besser handhabbare Schritte unterteilt. Zum Beispiel kann eine Plattform für Online-Shopping, wenn ein Kunde nach einem Produkt sucht, eine Anfrage an die Produktsuch-API senden und dann eine Anfrage an die Produktdetail-API, um weitere Informationen über die Produkte abzurufen. In diesem Artikel werden wir ein benutzerdefiniertes Plugin für das Apache APISIX API-Gateway erstellen, um Client-Anfragen zu behandeln, die in einer bestimmten Reihenfolge aufgerufen werden sollen.

Lernziele

Im Laufe des Artikels werden Sie Folgendes lernen:

  • Was sind verkettete API-Anfragen?
  • Beispiel für sequenzielle API-Aufrufe.
  • Wie man ein benutzerdefiniertes Pipeline-Request-Plugin für Apache APISIX erstellt.
  • Demo des Pipeline-Request-Plugins.

Pipelining API requests with API Gateway

Was ist eine verkettete API-Anfrage und warum brauchen wir sie?

Verkettete API-Anfragen (oder Pipeline-Anfragen oder sequenzielle API-Aufrufe) sind eine Technik in der Softwareentwicklung, um die Komplexität von API-Interaktionen zu bewältigen, bei denen Software mehrere API-Aufrufe benötigt, um eine Aufgabe zu erledigen. Es ähnelt der Batch-Anfrageverarbeitung, bei der mehrere API-Anfragen in einer einzigen Anfrage gruppiert und als Batch an den Server gesendet werden. Obwohl sie ähnlich erscheinen mögen, beinhaltet eine Pipeline-Anfrage das Senden einer einzelnen Anfrage an den Server, die eine Sequenz von API-Anfragen auslöst, die in einer definierten Reihenfolge ausgeführt werden. Jede API-Anfrage in der Sequenz kann die Anfrage- und Antwortdaten modifizieren, und die Antwort einer API-Anfrage wird als Eingabe für die nächste API-Anfrage in der Sequenz weitergegeben. Pipeline-Anfragen können nützlich sein, wenn ein Client eine Sequenz von abhängigen API-Anfragen ausführen muss, die in einer bestimmten Reihenfolge ausgeführt werden müssen.

In jedem Schritt der Pipeline können wir die Antwortdaten transformieren oder manipulieren, bevor sie an den nächsten Schritt weitergegeben werden. Dies kann in Situationen nützlich sein, in denen Daten normalisiert oder transformiert werden müssen oder sensible Daten herausgefiltert werden müssen, bevor sie an den Client zurückgegeben werden. Es kann helfen, die Gesamtlatenz zu reduzieren. Zum Beispiel kann ein API-Aufruf gemacht werden, während ein anderer auf eine Antwort wartet, wodurch die Gesamtzeit, die benötigt wird, um den Workflow abzuschließen, reduziert wird.

sequential API calls with API Gateway

Benutzerdefiniertes Pipeline-Request-Plugin für Apache APISIX

Ein API-Gateway kann der richtige Ort sein, um diese Funktionalität zu implementieren, da es alle Client-App-Anfragen abfangen und an die vorgesehenen Ziele weiterleiten kann. Wir werden Apache APISIX verwenden, da es eine beliebte Open-Source-API-Gateway-Lösung mit einer Reihe von integrierten Plugins ist. Zum Zeitpunkt der Entwicklung des aktuellen Blogbeitrags hatte APISIX jedoch keine offizielle Unterstützung für das Pipeline-Request-Plugin. Mit dem Wissen über die Fähigkeiten zur Entwicklung benutzerdefinierter Plugins von APISIX haben wir beschlossen, ein neues Plugin einzuführen, das dieselbe Funktion bietet. Es gibt ein Repo auf GitHub mit dem Quellcode, der in der Lua-Programmiersprache geschrieben ist, und einer Beschreibung des Pipeline-Request-Plugins.

Mit diesem Plugin können Sie eine Liste von Upstream-APIs angeben, die in einer bestimmten Reihenfolge aufgerufen werden sollen, um eine einzelne Client-Anfrage zu behandeln. Jede Upstream-API kann die Anfrage- und Antwortdaten modifizieren, und die Antwort einer Upstream-API wird als Eingabe für die nächste Upstream-API in der Pipeline weitergegeben. Die Pipeline kann in einer Route-Konfiguration definiert werden, und Sie können auch die Reihenfolge der API-URLs festlegen, in der die Pipeline sie ausführen soll.

Lassen Sie uns die Verwendung dieses Plugins anhand eines Beispiels verstehen. Angenommen, Sie haben zwei APIs - eine, die GET-Anfragen an /credit_cards sendet, um Kreditkarteninformationen abzurufen, und eine andere, die die vorherigen Antwortdaten im Body einer POST-Anfrage an /filter empfängt und dann sensible Daten (wie die Kreditkartennummer und das Ablaufdatum) herausfiltert, bevor sie die Antwort an den Client zurückgibt. Da der Kreditkarten-API-Endpunkt sensible Informationen zurückgibt, die nicht unbefugten Parteien zugänglich gemacht werden sollten. Das folgende Diagramm veranschaulicht den gesamten Datenfluss:

sequential API calls with API Gateway to filter

  1. Wenn ein Client eine Anfrage an den Kreditkarten-API-Endpunkt des API-Gateways sendet, um alle Kreditkarteninformationen abzurufen, leitet das API-Gateway eine Anfrage an den Backend-Service der Kreditkarte weiter, um die Kreditkartendaten abzurufen.
  2. Wenn die Anfrage erfolgreich ist und Kreditkartendaten zurückgibt, werden diese an den nächsten Schritt in der Pipeline weitergegeben, der der Sicherheitsdienst ist.
  3. Wenn die gefilterte Antwort vom Sicherheitsdienst empfangen wird, wird die kombinierte Antwort an den Client zurückgegeben.

Demo des Pipeline-Request-Plugins

Für diese Demo werden wir ein weiteres vorbereitetes Demo-Projekt auf GitHub verwenden, in dem Sie alle curl-Befehlsbeispiele finden, die in diesem Tutorial verwendet werden, APISIX ausführen und ein benutzerdefiniertes Plugin ohne zusätzliche Konfiguration mit einer Docker-Compose.yml-Datei aktivieren können.

Voraussetzungen

  • Docker wird verwendet, um den containerisierten etcd und APISIX zu installieren.
  • curl wird verwendet, um Anfragen an die APISIX Admin API zu senden. Sie können auch einfache Tools wie Postman verwenden, um mit der API zu interagieren.

Schritt 1: Installieren und Ausführen von APISIX und etcd

Sie können APISIX und etcd einfach installieren, indem Sie docker compose up aus dem Projektstammverzeichnis ausführen, nachdem Sie das Projekt geforkt/geklont haben. Sie werden feststellen, dass in der docker-compose.yml-Datei ein Volume ./custom-plugins:/opt/apisix/plugins:ro angegeben ist. Dies bindet das lokale Verzeichnis ./custom-plugins, in dem sich unsere pipeline-request.lua-Datei mit der Implementierung des benutzerdefinierten Plugins befindet, als schreibgeschütztes Volume im Docker-Container unter dem Pfad /opt/apisix/plugins ein. Dies ermöglicht es, benutzerdefinierte Plugins zur Laufzeit zu APISIX hinzuzufügen (Dieses Setup ist nur anwendbar, wenn Sie APISIX mit Docker ausführen).

Schritt 2: Erstellen der ersten Route mit dem Pipeline-Request-Plugin

Sobald APISIX läuft, verwenden wir den cURL-Befehl, der verwendet wird, um eine HTTP-PUT-Anfrage an den APISIX Admin API /routes-Endpunkt zu senden, um unsere erste Route zu erstellen, die auf den URI-Pfad /my-credit-cards hört.

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"
            }
         ]
      }
   }
}'

Der wichtige Teil der Konfiguration ist der Abschnitt "plugins", der angibt, dass das "pipeline-request"-Plugin für diese API-Route verwendet werden soll. Die Plugin-Konfiguration enthält ein "nodes"-Array, das die Sequenz von API-Anfragen definiert, die in der Pipeline ausgeführt werden sollen. Sie können dort eine oder mehrere APIs definieren. In diesem Fall besteht die Pipeline aus zwei Knoten: Der erste Knoten sendet eine Anfrage an die https://random-data-api.com/api/v2/credit_cards ****API, um Kreditkartendaten abzurufen, und der zweite Knoten sendet eine Anfrage an eine lokale API unter http://127.0.0.1:9080/filter, um sensible Daten aus den Kreditkarteninformationen herauszufiltern. Die zweite API wird lediglich eine serverlose Funktion sein, die das serverless-pre-function-Plugin von APISIX verwendet. Es fungiert lediglich als Backend-Service, um die Antwort der ersten API zu modifizieren.

Schritt 3: Erstellen der zweiten Route mit dem Serverless-Plugin

Als Nächstes konfigurieren wir eine neue Route mit der ID 2, die Anfragen an den /filter-Endpunkt in der Pipeline behandelt. Es aktiviert auch das serverless-pre-function-Plugin von APISIX, bei dem wir eine Lua-Funktion angeben, die vom Plugin ausgeführt werden soll. Diese Funktion ruft einfach den Anfrage-Body aus der vorherigen Antwort ab, ersetzt das Feld der Kreditkartennummer und lässt den Rest der Antwort unverändert. Schließlich setzt sie den aktuellen Antwort-Body auf den modifizierten Anfrage-Body und sendet eine HTTP-200-Antwort an den Client zurück. Sie können dieses Skript an Ihre Bedürfnisse anpassen, z. B. indem Sie den decodierten Body verwenden, um weitere Verarbeitungen oder Validierungen durchzuführen.

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"
            ]
        }
    }
}'

Schritt 3: Test des Setups

Jetzt ist es an der Zeit, die gesamte Konfiguration zu testen. Mit dem folgenden curl-Befehl senden wir eine HTTP-GET-Anfrage an den Endpunkt http://127.0.0.1:9080/my-credit-cards.

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

Wir haben die entsprechende Route im zweiten Schritt so konfiguriert, dass sie das pipeline-request-Plugin mit zwei Knoten verwendet. Diese Anfrage wird die Pipeline auslösen, um Kreditkarteninformationen vom Endpunkt https://random-data-api.com/api/v2/credit_cards abzurufen, sensible Daten mit dem Endpunkt http://127.0.0.1:9080/filter herauszufiltern und die modifizierte Antwort an den Client zurückzugeben. Siehe die Ausgabe:

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

Wie Sie sehen können, wird die Kreditkartennummer im Anfrage-Body (eigentlich ist es die Antwort des ersten API-Aufrufs in der Kette) durch Sternchen ersetzt.

Zusammenfassung

Bisher haben wir gelernt, dass unser benutzerdefiniertes Pipeline-Request-Plugin für das Apache APISIX API-Gateway es uns ermöglicht, eine Sequenz von API-Aufrufen als Pipeline in einer bestimmten Reihenfolge zu definieren. Wir können dieses neue Plugin auch in Kombination mit bestehenden Plugins verwenden, um Authentifizierung, Sicherheit und andere API-Gateway-Funktionen für unsere API-Endpunkte zu aktivieren.

Verwandte Ressourcen

Tags: