Bedingungen mit Ablaufvariablen

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:

Stimmt überein mit

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.

Für die Apigee API-Proxy-URL mit einem bedingten Ablauf konvertiert die Antwort XML in JSON und erfasst Analysen.

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:

  1. Wählen Sie im Proxy-Editor den Tab Entwickeln.
  2. Wählen Sie im linken Bereich Proxy-Endpunkte > Standard.

    Standard&quot; aus." class="l10n-absolute-url-src screenshot" l10n-attrs-original-order="class,width,alt,src" src="https://cloud.google.com/static/apigee/docs/api-platform/fundamentals/images/proxy-endpoints-default.png" width="35%" />

  3. Klicken Sie über dem Bereich Antwort auf die Schaltfläche +.

    Schaltfläche für bedingten Ablauf hinzufügen

  4. Geben Sie im Dialogfeld Bedingten Ablauf hinzufügen die folgenden Konfigurationen ein:
    • Ablaufname: Developers
    • Bedingungstyp: Path
    • Pfad: /developers

    Dialogfeld "Bedingten Ablauf hinzufügen"

    Die Bedingung wird ausgelöst (und Richtlinien werden ausgeführt), wenn ein Aufruf mit /developers am Ende des URI an den Proxy gesendet wird.

  5. 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.

Die hinzugefügten Abläufe werden im Bereich Antwort angezeigt:

Dialogfeld "Bedingten Ablauf hinzufügen"

Klassischer Proxy-Editor

Klicken Sie im Bereich Entwickeln des API-Proxy-Editors Navigator auf neben Standardeinstellung in den Proxy-Endpunkten.

Wenn Sie den Mauszeiger über das Pluszeichen neben „default“ halten, lautet der Mauszeigertext „Add New Flow“.

Geben Sie im Fenster Neuer bedingter Ablauf die folgenden Schlüsselkonfigurationen ein:

  • Ablaufname: Developers
  • Bedingungstyp: Path
  • Pfad: /developers

Im Bereich „New Conditional Flow“ ist ein Ablauf namens „Developers“ mit der Beschreibung „App developer registered with Developer Services“ konfiguriert.

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

Im Bereich „New Conditional Flow“ wird ein Ablauf namens „Apps“ mit der Beschreibung „Developer apps registered in Developer Services“ konfiguriert.

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.

Die neuen Abläufe für Apps und Entwickler werden im Navigationsbereich unter „Proxy Endpoints“ 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)"