Diese Seite gilt für Apigee und Apigee Hybrid.
Apigee Edge-Dokumentation aufrufen
Bedingte Anweisungen sind eine einheitliche Steuerstruktur in allen Programmiersprachen. Wie eine Programmiersprache unterstützt die API-Proxykonfiguration bedingte Anweisungen für Abläufe, Richtlinien, Schritte und RouteRules. Wenn Sie bedingte Anweisungen definieren, definieren Sie das dynamische Verhalten für Ihre API. Mit diesem dynamischen Verhalten können Sie XML beispielsweise nur für Mobilgeräte in JSON umwandeln oder an eine Backend-URL weiterleiten, die auf dem Inhaltstyp oder dem HTTP-Verb der Anfragenachricht basiert.
In diesem Thema erfahren Sie, wie Sie Bedingungen verwenden, um API-Verwaltungsfeatures dynamisch zur Laufzeit anzuwenden, ohne Code schreiben zu müssen.
Bedingte Anweisungen konfigurieren
Bedingtes Verhalten wird in API-Proxys mithilfe einer Kombination aus Bedingungen und Variablen implementiert. Eine bedingte Anweisung wird mit einem Bedingungselement erstellt. Die folgende Bedingung ist leer:
<Condition></Condition>
Zum Erstellen einer bedingten Anweisung fügen Sie einen Bedingungsoperator und eine Variable hinzu, um die folgende Syntax zu erstellen:
<Condition>VARIABLE_NAME OPERATOR "VALUE"</Condition>
Beispiele:
<Condition>request.verb = "GET"</Condition>
Unterstützte bedingte Operatoren sind =
(gleich), !=
(ungleich) und >
(größer als). Zur besseren Lesbarkeit können Sie auch die Bedingungen als Text schreiben: equals
, notequals
, greaterthan
.
Wenn Sie mit URI-Pfaden arbeiten, können Sie ~/
oder MatchesPath
verwenden. Außerdem können Sie mit dem Operator ~~
auch reguläre JavaRegex-Ausdrücke abgleichen.
Bedingungen werden verwendet, um bedingte API-Proxy-Abläufe für Backend-API-Ressourcen zu definieren, wie unter Erstellen von bedingten Abläufen für Backend-API-Ressourcen erstellen beschrieben. Eine vollständige Liste der Bedingungen finden Sie in der Referenz zu Bedingungen.
Variablen
Dazu werden die Werte von Variablen ausgewertet. Eine Variable ist das Attribut einer HTTP-Transaktion, die von einem API-Proxy ausgeführt wird, oder das Attribut einer API-Proxy-Konfiguration selbst. Immer wenn ein API-Proxy eine Anfrage von einer App erhält, stellt Apigee eine lange Liste von Variablen auf, die mit Elementen wie der Systemzeit, den Netzwerkinformationen der App, HTTP-Headern in Nachrichten, der API-Proxy-Konfiguration, Richtlinienausführungen und so weiter verknüpft sind. Dadurch wird ein umfassender Kontext erstellt, mit dem Sie bedingte Anweisungen einrichten können.
Für Variablen wird immer die Punktschreibweise verwendet. Beispielsweise sind HTTP-Header in der Anfragenachricht als Variablen mit dem Namen request.header.HEADER_NAME
verfügbar. Zum Auswerten des Content-type header
könnten Sie also die Variable request.header.Content-type
verwenden. Beispiel: request.header.Content-type = "application/json"
gibt an, dass der Inhaltstyp der Anfrage JSON sein soll.
Angenommen, Sie müssen eine bedingte Anweisung erstellen, mithilfe derer eine Richtlinie nur dann erzwungen wird, wenn eine Anfragenachricht vom Typ GET
ist. Um eine Bedingung zu erstellen, mit der das HTTP-Verb einer Anfrage ausgewertet wird, erstellen Sie unten die bedingte Anweisung. Die Variable in dieser Bedingung ist request.verb
. Der Wert der Variablen ist GET
. Der Operator ist =
.
<Condition>request.verb = "GET"</Condition>
Sie können auch Folgendes verwenden:
<Condition>request.verb equals "GET"</Condition>
Apigee verwendet eine solche Anweisung, um Bedingungen auszuwerten. Im obigen Beispiel wird der Wert „true“ zurückgegeben, wenn das mit der Anfrage verknüpfte HTTP-Verb GET
ist. Wenn das mit der Anfrage verknüpfte HTTP-Verb POST
lautet, wird die Anweisung als „false“ ausgewertet.
Für ein dynamisches Verhalten können Sie Bedingungen mit Abläufen, Schritten und Routingregeln verknüpfen.
Wenn Sie eine Bedingung an einen Ablauf anhängen, erstellen Sie einen bedingten Ablauf. Bedingte Abläufe werden nur ausgeführt, wenn die Bedingung als „true“ ausgewertet wird. Sie können beliebig viele Richtlinien an einen bedingten Ablauf anhängen. Mit bedingten Abläufen können Sie hochgradig spezialisierte Verarbeitungsregeln für Anfrage- oder Antwortnachrichten erstellen, die bestimmte Kriterien erfüllen.
So erstellen Sie beispielsweise einen Ablauf, der nur ausgeführt wird, wenn das Anfrageverb ein GET
-Vorgang ist:
<Flows> <Flow name="ExecuteForGETs"> <Condition>request.verb="GET"</Condition> </Flow> </Flows>
So erstellen Sie einen Ablauf für GET
-Anfragen und einen weiteren für POST
-Anfragen:
<Flows> <Flow name="ExecuteForGETs"> <Condition>request.verb="GET"</Condition> </Flow> <Flow name="ExecuteForPOSTs"> <Condition>request.verb="POST"</Condition> </Flow> </Flows>
Wie im folgenden Beispiel gezeigt, können Sie die Bedingung auf den Richtlinienschritt selbst anwenden. Die folgende Bedingung bewirkt, dass die VerifyApiKey-Richtlinie nur erzwungen wird, wenn eine Anfragenachricht eine POST
-Anfrage ist.
<PreFlow name="PreFlow"> <Request> <Step> <Condition>request.verb equals "POST"</Condition> <Name>VerifyApiKey</Name> </Step> </Request> </PreFlow>
Nachdem Sie diese bedingten Abläufe definiert haben, können Sie sie mit Richtlinien verknüpfen. Dadurch kann ein API-Proxy eine Reihe von Richtlinien für GET
-Anfragen und eine weitere Reihe von Richtlinien für POST
-Anfragen erzwingen.
Umfassende Referenzinformationen finden Sie in den folgenden Ressourcen:
Beispiel 1
Das folgende Beispiel zeigt einen einzelnen bedingten Namen mit dem Namen Convert-for-devices
, der im ProxyEndpoint-Antwortfluss konfiguriert wurde. Fügen Sie die Bedingung als Element zu der Entität hinzu, für die die Bedingung gilt. In diesem Beispiel ist die Bedingung eine Komponente des Ablaufs.
Daher wird der Ablauf ausgeführt, wenn die Anweisung mit true
ausgewertet wird.
<Flows> <Flow name="Convert-for-devices"> <Condition>(request.header.User-Agent = "Mozilla")</Condition> <Response> <Step><Name>ConvertToJSON</Name></Step> </Response> </Flow> </Flows>
Für jede von einer Anwendung empfangene Anfrage speichert Apigee die Werte aller HTTP-Header, die als Variablen vorhanden sind. Wenn die Anfrage einen HTTP-Header mit dem Namen User-Agent
enthält, werden dieser Header und sein Wert als Variable mit dem Namen request.header.User-Agent
gespeichert.
Bei der obigen ProxyEndpoint-Konfiguration prüft Apigee den Wert der Variable request.header.User-Agent
, um festzustellen, ob die Bedingung als „true“ ausgewertet wird.
Wenn die Bedingung als true
ausgewertet wird, d. h. der Wert der Variable request.header.User-Agent
gleich Mozilla
ist, wird der bedingte Ablauf ausgeführt und die XML-zu-JSON-Richtlinie namens ConvertToJSON
wird erzwungen. Andernfalls wird der Ablauf nicht ausgeführt und die XML-Antwort wird unverändert (im XML-Format) an die anfragende Anwendung zurückgegeben.
Beispiel 2
Nehmen wir ein konkretes Beispiel, in dem Sie die Antwortnachricht von XML in JSON umwandeln müssen, aber nur auf Mobilgeräten. Erstellen Sie zuerst die Richtlinie, die die XML-formatierte Antwort von der Weather API in JSON konvertiert:
<XMLToJSON name="ConvertToJSON"> <Options> </Options> <OutputVariable>response</OutputVariable> <Source>response</Source> </XMLToJSON>
Die Richtlinienkonfiguration oben weist den API-Proxy an, die Antwortnachricht aufzunehmen, eine Konvertierung von XML in JSON mit den Standardeinstellungen durchzuführen und das Ergebnis in die neue Antwortnachricht zu schreiben. Wenn Sie eine Anfrage-Nachricht von XML in JSON konvertieren, legen Sie einfach beide Werte auf request
fest.
Da Sie Antworten von XML in JSON konvertieren möchten, müssen Sie einen bedingten Antwortfluss für die Konvertierung konfigurieren. Wenn Sie beispielsweise alle Antworten von XML in JSON konvertieren möchten, bevor sie an die Client-App zurückgegeben werden, konfigurieren Sie den folgenden ProxyEndpoint-Antwortablauf.
<Flows> <Flow name="Convert-for-devices"> <Response> <Step><Name>ConvertToJSON</Name></Step> </Response> </Flow> </Flows>
Wenn Sie die API mit der Standardanfrage aufrufen, wird die Antwort in JSON formatiert.
Ihr Ziel ist jedoch, Wetterberichte nur in JSON umzuwandeln, wenn der anfordernde Client ein Mobilgerät ist. Um dieses dynamische Verhalten zu aktivieren, müssen Sie dem Ablauf eine bedingte Anweisung hinzufügen.
Bedingten Ablauf testen
In dieser Beispielanfrage ist der HTTP-Header User-Agent
auf Mozilla
gesetzt. Dadurch wird die bedingte Anweisung als „true“ ausgewertet und der bedingte Ablauf Convert-for-devices
wird ausgeführt.
curl -H "User-Agent:Mozilla" http://example.com/weather/forecastrss?w=12797282
Oder für eine optimierte Darstellung, wo Python verfügbar ist:
curl -H "User-Agent:Mozilla" http://example.com/weather/forecastrss?w=12797282 | python -mjson.tool
Beispielantwort:
. . . "yweather_forecast": [ { "code": "11", "date": "12 Dec 2012", "day": "Wed", "high": "55", "low": "36", "text": "Showers" }, { "code": "32", "date": "13 Dec 2012", "day": "Thu", "high": "56", "low": "38", "text": "Sunny" } ] } . . .
Eine Anfrage ohne den Header User-Agent
oder mit einem anderen Wert als Mozilla
führt zu einer Antwort im XML-Format.
$ curl http://example.com/weather/forecastrss?w=12797282
Die unveränderte XML-Antwort wird zurückgegeben.
Beispielantwort:
<yweather:forecast day="Wed" date="12 Dec 2012" low="36" high="55" text="Showers" code="11" /> <yweather:forecast day="Thu" date="13 Dec 2012" low="38" high="56" text="Sunny" code="32" />
Musterabgleich
In diesem Abschnitt wird beschrieben, wie Sie in einem Apigee-Ablauf einen Musterabgleich mit Bedingungen verwenden.
Operatoren
In diesem Abschnitt wird beschrieben, wie die folgenden Musterabgleichsoperatoren in bedingten Anweisungen verwendet werden:
Matches
-Operator: Einfacher Musterabgleich- JavaRegex-Operator: Gezielterer Abgleich
MatchesPath
-Operator: Pfadfragmentabgleich
Abgleich
Sehen wir uns zuerst die bedingten Operatoren Matches
und ~
an. Diese beiden Operatoren sind identisch, wobei die englische Version Matches
als besser lesbar gilt.
Zusammenfassung: Der Matches
-Operator bietet zwei Möglichkeiten. Sie geben entweder den String wörtlich ein oder führen einen Platzhalterabgleich mit *
aus. Der Platzhalter entspricht dann erwartungsgemäß null oder mehr Zeichen. Und so funktioniert es:
Die folgende XML-Datei zeigt eine Schrittbedingung. Sie führt die SomePolicy-Richtlinie aus, wenn die Bedingung als true ausgewertet wird. In diesem Beispiel testen wir die in Apigee integrierte Variable proxy.pathsuffix
, in der das Pfadsuffix der Anfrage gespeichert wird. Sie können jedoch den Wert einer beliebigen Ablaufvariable testen, die einen String enthält. Wenn der Basispfad der eingehenden Anfrage also /animals
und die Anfrage /animals/cat
ist, ist das Pfadsuffix der Literalstring /cat
.
<PreFlow name="PreFlow"> <Request> <Step> <Condition>(proxy.pathsuffix Matches "/cat")</Condition> <Name>SomePolicy</Name> </Step> </Request> <Response/> </PreFlow>
Frage: Welches Proxypfad-Suffix verursacht die Ausführung von SomePolicy? Es gibt nur eine Möglichkeit.
API-Aufruf:
GET http://example.com/matchtest/cat
Wird die Richtlinie ausgeführt? Ja, da das Suffix des Proxypfads exakt mit /cat
übereinstimmt. Sie wird nicht ausgeführt, wenn das Suffix /bat
oder /dog
oder /
oder anders lautet.
Betrachten wir nun diese bedingte Anweisung, in der das Platzhalterzeichen *
verwendet wird:
<Condition>(proxy.pathsuffix Matches "/*at")</Condition>
API-Aufruf:
GET http://example.com/matchtest/cat
Wird die Richtlinie ausgeführt? Ja, da der Platzhalter mit einem beliebigen Zeichen übereinstimmt und „"/cat
” eine Übereinstimmung ist.
API-Aufruf:
GET http://example.com/matchtest/bat
Wird die Richtlinie ausgeführt? Ja, da der Platzhalter mit einem beliebigen Zeichen übereinstimmt, sodass "/bat"
eine Übereinstimmung ist.
API-Aufruf:
GET http://example.com/matchtest/owl
Wird die Richtlinie ausgeführt? Sicher nicht – obwohl der Platzhalter mit o
übereinstimmt, stimmen die Buchstaben wl
nicht überein.
Verschieben Sie den Platzhalter jetzt an das Ende des Suffixes:
<Condition>(proxy.pathsuffix Matches "/cat*")</Condition>
API-Aufruf:
GET http://example.com/matchtest/cat
Wird die Richtlinie ausgeführt? Ja, da der Platzhalter null oder mehr Zeichen entspricht.
API-Aufruf:
GET http://example.com/matchtest/bat
Wird die Richtlinie ausgeführt? Nein, /bat
ist keine Übereinstimmung.
API-Aufruf:
GET http://example.com/matchtest/cat123
Wird die Richtlinie ausgeführt? Ja, der Platzhalter entspricht null oder mehr Zeichen, sodass 123
eine Übereinstimmung ergibt.
API-Aufruf:
GET http://example.com/matchtest/cat/bird/mouse
Wird die Richtlinie ausgeführt? Ja, da der Platzhalter null oder mehr Zeichen entspricht, sodass /bird/mouse
eine Übereinstimmung ergibt. Wie Sie sehen, kann ein Ausdruck wie dieser Probleme verursachen, da er alles nach den Literalzeichen abgleicht.
Frage: Berücksichtigt der Matches
-Operator die Groß-/Kleinschreibung?
Ja. Angenommen, Sie haben eine Bedingung wie diese:
<Condition>(proxy.pathsuffix Matches "/*At")</Condition>
API-Aufruf:
GET http://example.com/matchtest/cat
Wird die Richtlinie ausgeführt? Nein, der Platzhalter entspricht einem beliebigen Buchstaben unabhängig von der Groß- und Kleinschreibung, aber das kleingeschriebene a
entspricht nicht A
API-Aufruf:
GET http://example.com/matchtest/bAt
Wird die Richtlinie ausgeführt? Ja, die Groß-Kleinschreibung stimmt überein.
Frage: Wie maskiere ich Zeichen mit dem Matches
-Operator?
Verwenden Sie das Zeichen %
, um reservierte Zeichen zu maskieren. Beispiele:
<Condition>(proxy.pathsuffix Matches "/c%*at")</Condition>
API-Aufruf:
GET http://example.com/matchtest/cat
Wird die Richtlinie ausgeführt? Nein, der Matches
-Operator sucht nach dem Literalstring c*at
.
API-Aufruf:
GET http://example.com/matchtest/c*at
Frage: Wird die Richtlinie ausgeführt?
Ja, dieser Pfad ist zwar etwas ungewöhnlich, stimmt aber überein.
JavaRegex
Wie Sie sehen, eignet sich der Operator Matches
für einfache Situationen. Sie können jedoch einen anderen Operator verwenden, den JavaRegex- oder ~~
-Operator. Diese beiden Operatoren sind identisch, aber JavaRegex wird als besser lesbar betrachtet. JavaRegex heißt so, weil damit ein Abgleich des regulären Ausdrucks möglich ist. Apigee folgt dabei denselben Regeln wie die Klassen im java.util.regex-Paket in der Java-Sprache. Die Art und Weise, wie der JavaRegex-Operator funktioniert, unterscheidet sich sehr vom Matches
-Operator. Daher ist es wichtig, die beiden nicht zu verwechseln.
Zusammenfassung: Mit dem JavaRegex-Operator können Sie in regulären Anweisungen die Syntax für reguläre Ausdrücke verwenden.
Der folgende Code zeigt eine Schrittbedingung: Führt die SomePolicy-Richtlinie aus, wenn die Bedingung true
ergibt. In diesem Beispiel testen wir die in Apigee integrierte Variable proxy.pathsuffix
, in der das Pfadsuffix der Anfrage gespeichert wird. Wenn der Basispfad der eingehenden Anfrage /animals
und die Anfrage /animals/cat
ist, ist das Pfadsuffix der Literalstring /cat
.
<PreFlow name="PreFlow"> <Request> <Step> <Condition>(proxy.pathsuffix JavaRegex "/cat")</Condition> <Name>SomePolicy</Name> </Step> </Request> <Response/> </PreFlow>
Frage: Welches Proxypfad-Suffix verursacht die Ausführung von SomePolicy? Wie beim Matches
-Operator gibt es auch hier nur eine Möglichkeit.
API-Aufruf:
GET http://example.com/matchtest/cat
Wird die Richtlinie ausgeführt? Ja, da das Suffix des Proxypfads exakt mit /cat
übereinstimmt. Sie wird nicht ausgeführt, wenn das Suffix /bat
oder /dog
oder anders lautet.
Erstellen wir nun einen regulären Ausdruck mit dem Quantifizierer *
. Dieser Quantifizierer entspricht null oder mehr der vorherigen Zeichen.
<Condition>(proxy.pathsuffix JavaRegex "/c*t")</Condition>
API-Aufruf:
GET http://example.com/matchtest/cat
Wird die Richtlinie ausgeführt? Nein. Der Quantifizierer *
entspricht null oder mehr der vorherigen Zeichen, also c
.
API-Aufruf:
GET http://example.com/matchtest/ccccct
Wird die Richtlinie ausgeführt? Ja, da der Platzhalter keinem oder mehreren der vorherigen Zeichen entspricht.
Als Nächstes verwenden wir den Quantifizierer ?
, der mit dem vorherigen Zeichen einmal oder keinmal übereinstimmt.
<Condition>(proxy.pathsuffix JavaRegex "/ca?t")</Condition>
API-Aufruf:
GET http://example.com/matchtest/cat
Wird die Richtlinie ausgeführt? Ja. Der Quantifizierer ?
entspricht null oder einem Vorkommen des vorhergehenden Zeichens, also a
.
API-Aufruf:
GET http://example.com/matchtest/ct
Wird die Richtlinie ausgeführt? Ja. Der Quantifier ?
entspricht einem oder keinem des vorherigen Zeichens. In diesem Fall gibt es kein a
-Zeichen, sodass die Bedingung als true
ausgewertet wird.
API-Aufruf:
GET http://example.com/matchtest/caat
Wird die Richtlinie ausgeführt? Nein. Der Quantifizierer ?
entspricht einem der vorherigen Zeichen, also einem a
.
Als Nächstes verwenden wir den regulären Ausdruck [abc]
oder Gruppierungen. Er entspricht dem Zeichen a
, b
oder c
.
<Condition>(proxy.pathsuffix JavaRegex "/[cbr]at")</Condition>
API-Aufruf:
GET http://example.com/matchtest/cat
Wird die Richtlinie ausgeführt? Ja. Wir verwenden hier reguläre Ausdrücke und der Ausdruck [cbr]
entspricht einem c
, b
oder r
. Diese Aufrufe sind auch Übereinstimmungen:
GET http://example.com/matchtest/bat
GET http://example.com/matchtest/rat
Dies ist jedoch keine Übereinstimmung:
GET http://example.com/matchtest/mat
Frage: Berücksichtigt der JavaRegex-Operator die Groß-/Kleinschreibung?
Ja. Angenommen, Sie haben eine Bedingung wie diese:
<Condition>(proxy.pathsuffix JavaRegex "/ca?t")</Condition>
API-Aufruf:
GET http://example.com/matchtest/cat
Wird die Richtlinie ausgeführt? Ja, der Regex stimmt mit null oder einem der vorhergehenden Zeichen überein, also a
.
API-Aufruf:
GET http://example.com/matchtest/cAt
Frage: Wird die Richtlinie ausgeführt?
Nein, weil das großgeschriebene A
nicht mit dem kleingeschriebenen a
übereinstimmt.
MatchesPath
Der Operator MatchesPath
kann auch so angegeben werden: ~/
. Sie ähnelt den Operatoren Matches
(~
) und JavaRegex (~~
). MatchesPath
ist jedoch völlig anders.
Beachten Sie, dass dieser Operator einen Pfad als eine Zusammensetzung aus verschiedenen Teilen betrachtet. Wenn der Pfad also /animals/cats/wild
lautet, können Sie sich den Pfad als Zusammenstellung der Teile /animals
, /cats
und /wild
vorstellen.
Mit dem Operator MatchesPath
können Sie zwei Platzhalterschreibweisen verwenden: ein einzelnes Sternchen (*) und ein doppeltes Sternchen (**
). Das einzelne Sternchen entspricht einem Pfadelement. Das doppelte Sternchen entspricht einem oder mehreren Pfadelementen.
Sehen wir uns ein Beispiel an: In diesem Beispiel testen wir die in Apigee integrierte Variable proxy.pathsuffix
, in der das Pfadsuffix der Anfrage gespeichert wird. Sie können jedoch den Wert einer beliebigen Ablaufvariable testen, die einen String enthält.
<PreFlow name="PreFlow"> <Request> <Step> <Condition>(proxy.pathsuffix MatchesPath "/animals/*")</Condition> <Name>SomePolicy</Name> </Step> </Request> <Response/> </PreFlow>
Frage: Welches Proxypfad-Suffix verursacht die Ausführung von SomePolicy?
API-Aufruf:
GET http://example.com/matchtest/animals
Frage: Wird die Richtlinie ausgeführt?
Nein, da für die Bedingung ein weiteres Pfadelement nach /animals
benötigt wird, wie durch /*
angegeben.
API-Aufruf:
GET http://example.com/matchtest/animals
/
Wird die Richtlinie ausgeführt? Ja, der Pfad enthält ein weiteres Pfadelement (der Teil nach /animals/
), ist aber leer.
API-Aufruf:
GET http://example.com/matchtest/animals/cats
Wird die Richtlinie ausgeführt? Ja, da der Pfad eindeutig ein Element (/cats
) enthält, das nach /animals
folgt.
API-Aufruf:
GET http://example.com/matchtest/animals/cats/wild
Frage: Wird die Richtlinie ausgeführt?
Nein, weil das einzelne Sternchen nur mit einem Pfadelement übereinstimmt und diese API mehrere Elemente nach /animals
enthält.
Verwenden wir jetzt das doppelte Sternchen:
<PreFlow name="PreFlow"> <Request> <Step> <Condition>(proxy.pathsuffix MatchesPath "/animals/**")</Condition> <Name>SomePolicy</Name> </Step> </Request> <Response/> </PreFlow>
Frage: Welches Proxypfad-Suffix verursacht die Ausführung von SomePolicy?
API-Aufruf:
GET http://example.com/matchtest/animals
Wird die Richtlinie ausgeführt? Nein, da für die Bedingung mindestens ein Pfadelement erforderlich ist, das durch /**
angegeben wird.
API-Aufruf:
GET http://example.com/matchtest/animals
/
Wird die Richtlinie ausgeführt?
Ja, der Pfad enthält ein weiteres Pfadelement (der Teil nach /animals/
), ist aber leer.
API-Aufruf:
GET http://example.com/matchtest/animals/cats
Wird die Richtlinie ausgeführt?
Ja, da der Pfad mindestens ein Element enthält, das nach /animals
folgt.
API-Aufruf:
GET http://example.com/matchtest/animals/cats/wild
Wird die Richtlinie ausgeführt?
Ja, da der Pfad mehr als ein Element enthält, das nach /animals
folgt.
Sternchen kombinieren
Sie können Kombinationen aus einem einzelnen Sternchen (*) und doppelten Sternchen (**) verwenden, um den Pfadabgleich zu verfeinern.
<PreFlow name="PreFlow"> <Request> <Step> <Condition>(proxy.pathsuffix MatchesPath "/animals/*/wild/**")</Condition> <Name>SomePolicy</Name> </Step> </Request> <Response/> </PreFlow>
API-Aufruf:
Alle folgenden API-Aufrufe liefern eine Übereinstimmung:
GET http://example.com/matchtest/animals/cats/wild/
und
GET http://example.com/matchtest/animals/dogs/wild/austrailian
und
GET
http://example.com/matchtest/animals/birds/wild/american/finches
API-Ressourcen
RESTful-Dienste sind Sammlungen von API-Ressourcen. Eine API-Ressource ist ein URI-Pfadfragment, das eine Entität identifiziert, auf die Entwickler durch Aufrufen Ihrer API zugreifen können. Wenn Ihr Dienst beispielsweise Wetterberichte und Wettervorhersagen bereitstellt, kann Ihr Backend-Dienst zwei API-Ressourcen definieren:
http://mygreatweatherforecast.com/reports
http://mygreatweatherforecast.com/forecasts
Wenn Sie einen API-Proxy erstellen (wie unter Ersten API-Proxy erstellen gezeigt), müssen Sie zumindest eine Alias-Basis-URL erstellen, die Ihrem Backend-Dienst zugeordnet ist. Beispiele:
Backend-Basis-URL | Neue/entsprechende API-Proxy-URL |
---|---|
http://mygreatweatherforecast.com |
http://example.com/mygreatweatherforecast |
An dieser Stelle können Sie mit beiden URLs API-Aufrufe an Ihr Backend senden. Wenn Sie jedoch die API-Proxy-URL verwenden, wird es interessant.
Zusätzlich zu den API-Analysen, die Apigee bei der Verwendung des API-Proxys sammelt, können Sie mit Proxys auch bedingte Abläufe definieren, die den Ressourcen in Ihrem Backend zugeordnet sind. Im Wesentlichen bedeutet dies: Wenn ein GET
-Aufruf bei der Ressource /reports
eingeht, muss Apigee handeln.
In der folgenden Abbildung ist der Verhaltensunterschied zwischen zwei URLs zu sehen, die letztendlich auf dasselbe Backend zugreifen. Die erste ist die URL der nicht Proxy-Ressource. Die andere ist ein Apigee API-Proxy mit einem bedingten Ablauf für dieselbe Backend-Ressource. Weitere Informationen zu bedingten Abläufen finden Sie weiter unten.
So werden API-Proxys zu bestimmten Backend-Ressourcen zugeordnet
Wenn eine API-Proxy-URL der Basis-URL des Backend-Dienstes (beim Erstellen des Proxys) zugeordnet ist, können Sie bedingte Abläufe bestimmten Ressourcen zuordnen, wie z. B. die bereits erwähnten Ressourcen /reports
und /forecasts
.
Angenommen, Sie möchten, dass Apigee etwas unternimmt, wenn Aufrufe an die Ressource /reports
oder /forecasts
erfolgen. Sie teilen Apigee dann nicht mit, was es tun soll, sondern nur, dass Aufrufe an diese Ressourcen überwacht werden. Dazu verwenden Sie Bedingungen. In Ihrem Apigee API-Proxy können Sie bedingte Abläufe für /reports
und /forecasts
erstellen. Zu Konzeptzwecken veranschaulicht die folgende API-Proxy-XML, wie diese Bedingungen aussehen könnten.
<Flows> <Flow name="reports"> <Description/> <Request/> <Response/> <Condition>(proxy.pathsuffix MatchesPath "/reports") and (request.verb = "GET")</Condition> </Flow> <Flow name="forecasts"> <Description/> <Request/> <Response/> <Condition>(proxy.pathsuffix MatchesPath "/forecasts") and (request.verb = "GET")</Condition> </Flow> </Flows>
Diese Bedingungen geben vor: Wenn eine GET
-Anfrage mit /reports
und /forecasts
in der URL eingeht, führt Apigee das aus, was Sie als API-Entwickler über die Richtlinien vorgeben, die Sie mit diesen Abläufen verknüpfen.
Hier sehen Sie ein Beispiel dafür, wie Sie Apigee mitteilen, was zu tun ist, wenn eine Bedingung erfüllt ist. Wenn in der folgenden API-Proxy-XML eine GET
-Anfrage an https://example.com/mygreatweatherforecast/reports
gesendet wird, führt Apigee in der Antwort die Richtlinie XML-to-JSON-1
aus.
<Flows> <Flow name="reports"> <Description/> <Request/> <Response> <Step> <Name>XML-to-JSON-1</Name> </Step> </Response> <Condition>(proxy.pathsuffix MatchesPath "/reports") and (request.verb = "GET")</Condition> </Flow>
Zusätzlich zu diesen optionalen bedingten Abläufen enthält jeder API-Proxy auch zwei Standardabläufe: einen <PreFlow>
, der vor den bedingten Abläufen ausgeführt wird, und einen <PostFlow>
, der nach den bedingten Abläufen ausgeführt wird. Diese sind nützlich, um Richtlinien auszuführen, wenn ein beliebiger Aufruf an einen API-Proxy erfolgt. Wenn Sie beispielsweise den API-Schlüssel einer Anwendung bei jedem Aufruf prüfen möchten, können Sie unabhängig vom Zugriff auf die Backend-Ressource eine Richtlinie zum Prüfen des API-Schlüssels im <PreFlow>
bereitstellen. Weitere Informationen zu Abläufen finden Sie unter Abläufe konfigurieren.
Bedingte Abläufe für Backend-Ressourcen erstellen
Das Definieren bedingter Abläufe für Backend-Ressourcen in einem API-Proxy ist optional. Mit diesen bedingten Abläufen haben Sie jedoch die Möglichkeit, differenzierte Verwaltungs- und Monitoringaufgaben auszuführen.
Sie haben folgende Möglichkeiten:
- Verwaltungsaufgaben an die Semantik Ihres API-Modells anpassen
- Richtlinien und skriptbasiertes Verhalten auf einzelne Ressourcenpfade (URIs) anwenden
- Detaillierte Messwerte für Analytics-Dienste erfassen
Angenommen, Sie müssen auf Ihre Backend-Ressourcen /developers
bis /apps
verschiedene Logiktypen anwenden.
Fügen Sie dazu Ihrem API-Proxy zwei bedingte Abläufe hinzu: /developers
und /apps
.
Neuer Proxy-Editor
So fügen Sie einen bedingten Ablauf hinzu:
- Wählen Sie im Proxy-Editor den Tab Entwickeln.
- Wählen Sie im linken Bereich Proxy-Endpunkte > Standard.
- Klicken Sie über dem Bereich Antwort auf die Schaltfläche +.
- Geben Sie im Dialogfeld Bedingten Ablauf hinzufügen die folgenden Konfigurationen ein:
- Ablaufname:
Developers
- Bedingungstyp:
Path
- Pfad:
/developers
Die Bedingung wird ausgelöst (und Richtlinien werden ausgeführt), wenn ein Aufruf mit
/developers
am Ende des URI an den Proxy gesendet wird. - Ablaufname:
- Fügen Sie nun einen bedingten Ablauf für
/apps
hinzu. Nehmen Sie an, dass die Bedingung sowohl für den URI als auch für dasPOST
-Verb in einer Anfrage ausgelöst werden soll. Die Konfiguration umfasst Folgendes:- Ablaufname:
Apps
- Bedingungstyp:
Path and Verb
- Pfad:
/apps
- Verb:
POST
Die Bedingung wird ausgelöst (und Richtlinien werden ausgeführt), wenn ein Aufruf mit
/apps
am Ende des URI und einemPOST
-Verb an den Proxy gesendet wird. - Ablaufname:
Die hinzugefügten Abläufe werden im Bereich Antwort angezeigt:
Klassischer Proxy-Editor
Klicken Sie im Bereich Entwickeln des API-Proxy-Editors Navigator auf neben Standardeinstellung in den Proxy-Endpunkten.
Geben Sie im Fenster Neuer bedingter Ablauf die folgenden Schlüsselkonfigurationen ein:
- Ablaufname:
Developers
- Bedingungstyp:
Path
- Pfad:
/developers
Die Bedingung wird ausgelöst (und Richtlinien werden ausgeführt), wenn ein Aufruf mit /developers
am Ende des URI an den Proxy gesendet wird.
Fügen Sie nun einen bedingten Ablauf für /apps
hinzu. Nehmen Sie an, dass die Bedingung sowohl für den URI als auch für das POST
-Verb in einer Anfrage ausgelöst werden soll. Die Konfiguration umfasst Folgendes:
- Ablaufname:
Apps
- Bedingungstyp:
Path and Verb
- Pfad:
/apps
- Verb:
POST
Die Bedingung wird ausgelöst (und Richtlinien werden ausgeführt), wenn ein Aufruf mit /apps
am Ende des URI und einem POST
-Verb an den Proxy gesendet wird.
Im Bereich Navigator werden neue Abläufe für Apps und Entwickler angezeigt.
Wählen Sie einen der Abläufe aus, um die Konfiguration des bedingten Ablaufs in der Codeansicht des API-Proxy-Editors aufzurufen:
<Flow name="Apps"> <Description>Developer apps registered in Developer Services</Description> <Request/> <Response/> <Condition>(proxy.pathsuffix MatchesPath "/apps") and (request.verb = "POST")</Condition> </Flow>
API-Ressourcen sind einfach nur bedingte Abläufe, die den URI-Pfad der eingehenden Anfrage auswerten. (Die Variable proxy.pathsuffix
gibt den URI der Anfrage an, der dem in der ProxyEndpoint-Konfiguration konfigurierten BasePath entspricht.)
Jede von Ihnen definierte API-Ressource wird durch einen bedingten Ablauf im API-Proxy implementiert. (Siehe Abläufe konfigurieren)
Nachdem Sie den API-Proxy in der Testumgebung bereitgestellt haben, führt die folgende Abfrage
http://example.com/PROXY_PATH/apps
dazu, dass die Bedingung zu true
ausgewertet und dieser Ablauf zusammen mit allen zugehörigen Richtlinien ausgeführt wird.
Die folgende Beispielbedingung verwendet einen regulären Java-Ausdruck, um Aufrufe für die Ressource /apps
mit oder ohne abschließendem Schrägstrich (/apps
oder /apps/**
) zu erkennen:
<Condition>(proxy.pathsuffix JavaRegex "/apps(/?)") and (request.verb = "POST")</Condition>
Weitere Informationen zu dieser Art von Bedingung finden Sie unter How to match regardless whether there is a trailing "/" ... in der Apigee Community.
Hierarchische URIs modellieren
In einigen Fällen stehen hierarchische API-Ressourcen zur Verfügung. Beispielsweise bietet die Developer Apps List API eine Methode zum Auflisten aller Anwendungen, die zu einem Entwickler gehören. Der URI-Pfad lautet:
/developers/DEVELOPER_EMAIL/apps
Möglicherweise gibt es Ressourcen, bei denen für jede Entität in einer Sammlung eine eindeutige ID generiert wird, die manchmal so annotiert wird:
/genus/:id/species
Dieser Pfad wird gleichermaßen auf die folgenden beiden URIs angewendet:
/genus/18904/species /genus/17908/species
Um diese Struktur in einer API-Ressource darzustellen, können Sie Platzhalter verwenden. Beispiele:
/developers/*/apps /developers/*example.com/apps /genus/*/species
Dadurch werden die hierarchischen URIs entsprechend als API-Ressourcen aufgelöst.
In einigen Fällen, insbesondere bei hierarchischen APIs, können Sie auch alles unter einem bestimmten URI-Fragment auflösen. Verwenden Sie dazu einen doppelten Sternchenplatzhalter in Ihrer Ressourcendefinition. Angenommen, Sie definieren die folgende API-Ressource:
/developers/**
Diese API-Ressource löst die folgenden URI-Pfade auf:
/developers/DEVELOPER_EMAIL/apps /developers/DEVELOPER_EMAIL/keys /developers/DEVELOPER_EMAIL/apps/APP_ID/keys
So sieht die Bedingung für den bedingten Ablauf in der API-Proxy-Definition aus:
<Condition>(proxy.pathsuffix MatchesPath "/developers/**") and (request.verb = "POST")</Condition>
Weitere Beispiele
Mit einer Routingregel verknüpfte Bedingung
<RouteRule name="default"> <!--this routing executes if the header indicates that this is an XML call. If true, the call is routed to the endpoint XMLTargetEndpoint--> <Condition>request.header.content-type = "text/xml"</Condition> <TargetEndpoint>XmlTargetEndpoint</TargetEndpoint> </RouteRule>
Mit einer Richtlinie verknüpfte Bedingung
<Step> <!--the policy MaintenancePolicy only executes if the response status code is exactly 503 --> <Condition>response.status.code = 503</Condition> <Name>MaintenancePolicy</Name> </Step>
Bedingter Ablauf
<!-- this entire flow is executed only if the request verb is a GET--> <Flow name="GetRequests"> <Condition>request.verb="GET"</Condition> <Request> <Step> <!-- this policy only executes if request path includes a term like statues--> <Condition>request.path ~ "/statuses/**"</Condition> <Name>StatusesRequestPolicy</Name> </Step> </Request> <Response> <Step> <!-- this condition has multiple expressions. The policy executes if the response code status is exactly 503 or 400--> <Condition>(response.status.code = 503) or (response.status.code = 400)</Condition> <Name>MaintenancePolicy</Name> </Step> </Response> </Flow>
Beispieloperatoren in Bedingungen
Beispiele für Operatoren zum Erstellen von Bedingungen:
request.header.content-type = text/xml
request.header.content-length < 4096 && request.verb = PUT
response.status.code = 404 || response.status.code = 500
request.uri MatchesPath /*/statuses/**
request.queryparam.q0 NotEquals 10
Praktisches Beispiel: /
am Ende eines Pfads ignorieren
Apigee-Entwickler möchten in der Regel beide Pfadsuffixe verarbeiten: /cat
und /cat/
. Dies liegt daran, dass manche Nutzer oder Clients Ihre API mit dem zusätzlichen Schrägstrich am Ende des Pfads aufrufen und Sie in der Lage sein müssen, dies in Ihren bedingten Anweisungen zu berücksichtigen. Dieser konkrete Anwendungsfall wurde in
How to match regardless whether there is a trailing '/' on the url... behandelt.
Sie können dies auch ohne Regex erreichen. Gehen Sie dazu so vor:
<PreFlow name="PreFlow"> <Request> <Step> <Condition>(proxy.pathsuffix = "/cat") OR (proxy.pathsuffix = "/cat/")</Condition> <Name>SomePolicy</Name> </Step> </Request> <Response/> </PreFlow>
Das ist eine gute Option. Sie ist gut verständlich und lesbar.
Sie können dies auch mit Regex erreichen. Gehen Sie dazu so vor. Die Klammern können zum Gruppieren des regulären Ausdrucks der Anweisung verwendet werden, sind aber nicht erforderlich.
<Condition>(proxy.pathsuffix JavaRegex "/cat(/?)"</Condition>
API-Aufrufe:
GET http://example.com/matchtest/cat
or GET http://example.com/matchtest/cat
/
Wird die Richtlinie ausgeführt? Ja. Beachten Sie, dass das Zeichen ?
in einem regulären Ausdruck bedeutet: Übereinstimmung mit null oder einem der vorherigen Zeichen. Daher sind sowohl /cat
als auch /cat/
Übereinstimmungen.
API-Aufruf:
GET http://example.com/matchtest/cat/spotted
Wird die Richtlinie ausgeführt? Nein. Der reguläre Ausdruck entspricht null oder nur einem Vorkommen des vorherigen Zeichens und nichts anderes ist zulässig.
Beliebige Strings mit JavaRegex abgleichen
In allen Beispielen in diesem Thema wird gezeigt, wie Sie eine der integrierten Flussvariablen abgleichen können: proxy.pathsuffix
. Es ist gut zu wissen, dass Sie den Musterabgleich für jeden beliebigen String oder jede Variable machen können, unabhängig davon, ob es sich um eine integrierte Ablaufvariable wie proxy.pathsuffix
handelt.
Wenn Sie beispielsweise eine Bedingung haben, mit der beliebige Strings getestet werden, z. B. ein String, der in einer Backend-Nutzlast zurückgegeben wird, oder ein String, der von einer Authentifizierungsserversuche zurückgegeben wird, können Sie übereinstimmende Operatoren zum Testen verwenden. Wenn Sie JavaRegex
verwenden, wird der reguläre Ausdruck mit dem gesamten Substring verglichen. Wenn der Betreff abc
lautet und der reguläre Ausdruck [a-z]
lautet, gibt es keine Übereinstimmung, da [a-z]
genau einem Alphazeichen entspricht. Der Ausdruck [a-z]+
funktioniert ebenso wie [a-z]*
und [a-z]{3}
.
Sehen wir uns ein konkretes Beispiel an. Angenommen, der Authentifizierungsserver gibt eine Liste der Rollen als kommagetrennten String zurück: editor, author, guest
.
Um das Vorhandensein der Bearbeiterrolle zu testen, funktioniert diese Konstruktion nicht, da editor
nur ein Teil des gesamten Strings ist.
<Condition>returned_roles ~~ "editor"</Condition>
Diese Konstruktion funktioniert jedoch:
<Condition>returned_roles ~~ ".*\beditor\b.*")</Condition>
Sie funktioniert, da sie Worttrennungen und andere Teile des Strings mit dem Präfix .*
und dem Suffix berücksichtigt.
In diesem Beispiel können Sie auch editor
mit dem Matches
-Operator testen:
<Condition>returned_roles ~~ "*editor*")</Condition>
Wenn Sie hingegen eine höhere Genauigkeit benötigen, ist JavaRegex häufig die bessere Wahl.
Doppelte Anführungszeichen in JavaRegex-Ausdrücken maskieren
Für die Bedingungssyntax muss ein JavaRegex-Ausdruck in doppelte Anführungszeichen gesetzt werden. Wenn Sie also einen regulären Ausdruck mit doppelten Anführungszeichen haben, benötigen Sie eine alternative Methode für den Abgleich. Die Antwort lautet Unicode. Beispiel: Sie übergeben einen Header mit doppelten Anführungszeichen. Beispiel:
-H 'content-type:multipart/related; type="application/xop+xml"'
Wenn Sie versuchen, diesen Header mit einer Regex-Bedingung abzugleichen, erhalten Sie den Fehler Invalid Condition
, da der Ausdruck doppelte Anführungszeichen enthält:
request.header.Content-Type ~~ "(multipart\/related)(; *type="application\/xop\+xml\")"
Die Lösung besteht darin, die ASCII-basierten Anführungszeichen durch die Unicode-Entsprechung \u0022
zu ersetzen. Der folgende Ausdruck ist beispielsweise gültig und erzeugt das erwartete Ergebnis:
request.header.Content-Type ~~ "(multipart\/related)(; *type=\u0022application\/xop\+xml\u0022)"