Conditions avec variables de flux

Vous consultez la documentation d'Apigee Edge.
Consultez la documentation Apigee X.
en savoir plus

Les instructions conditionnelles sont une structure de contrôle commune à tous les langages de programmation. À l'instar d'un langage de programmation, la configuration des proxys d'API accepte les instructions conditionnelles pour les flux, les règles, les étapes et les règles de routage. La définition d'instructions conditionnelles vous permet de définir le comportement dynamique de votre API. Ce comportement dynamique vous permet par exemple de convertir le format XML au format JSON uniquement pour les appareils mobiles, ou de router vers une URL de backend en fonction du type de contenu ou du verbe HTTP du message de requête.

Cette rubrique explique comment utiliser des conditions pour appliquer dynamiquement les fonctionnalités de gestion des API lors de l'exécution, sans avoir à écrire de code.

Configurer des instructions conditionnelles

Le comportement conditionnel est mis en œuvre dans les proxys d'API à l'aide d'une combinaison de conditions et de variables. Une instruction conditionnelle est créée à l'aide d'un élément de condition. La condition suivante est vide :

<Condition></Condition>

Pour créer une instruction conditionnelle, ajoutez un opérateur conditionnel et une variable pour créer la structure suivante :

<Condition>{variable.name}{operator}{"value"}</Condition>

Les opérateurs conditionnels acceptés incluent = (est égal à), != (différent de) et > (supérieur à). Pour plus de lisibilité, vous pouvez également écrire les conditions sous forme de texte : equals, notequals, greaterthan.

Lorsque vous travaillez avec des chemins d'accès d'URI, vous pouvez utiliser ~/ ou MatchesPath. Vous pouvez également mettre en correspondance des expressions régulières JavaRegex à l'aide de l'opérateur ~~.

Les conditions permettent de définir les flux conditionnels du proxy d'API pour les ressources de l'API backend, décrites dans la section Créer des flux conditionnels aux ressources de l'API backend. Pour obtenir une liste complète des conditions, consultez la documentation de référence sur les conditions.

Variables

Les conditions réalisent leur tâche en évaluant les valeurs des variables. Une variable est une propriété d'une transaction HTTP exécutée par un proxy d'API ou une propriété de configuration de proxy d'API elle-même. Chaque fois qu'un proxy d'API reçoit une requête d'une application, Apigee Edge remplit une longue liste de variables associées à des éléments tels que l'heure système, les informations réseau de l'application, les en-têtes HTTP sur les messages, la configuration du proxy d'API, les exécutions de stratégie, etc. Cela permet de créer un contexte enrichi que vous pouvez utiliser pour configurer des instructions conditionnelles.

Les variables utilisent toujours une notation en pointillés. Par exemple, les en-têtes HTTP du message de requête sont disponibles sous la forme de variables appelées request.header.{header_name}. Ainsi, pour évaluer l'en-tête "Content-type", vous pouvez utiliser la variable request.header.Content-type. Par exemple, request.header.Content-type = "application/json" indique que le type de contenu de la requête doit être JSON.

Imaginez que vous deviez créer une instruction conditionnelle qui entraînerait l'application d'une stratégie uniquement lorsqu'un message de requête est un GET. Pour créer une condition qui évalue le verbe HTTP d'une requête, vous devez créer l'instruction conditionnelle ci-dessous. La variable de cette condition est request.verb. La valeur de la variable est GET. L'opérateur est =.

<Condition>request.verb = "GET"</Condition>
Vous pouvez également utiliser :
<Condition>request.verb equals "GET"</Condition>

Edge utilise une telle instruction pour évaluer les conditions. L'exemple ci-dessus est évalué à "true" si le verbe HTTP associé à la requête est GET. Si le verbe HTTP associé à la requête est POST, l'instruction est évaluée comme étant "false".

Pour activer le comportement dynamique, vous pouvez associer des conditions aux flux, aux étapes et aux règles de routage.

Lorsque vous associez une condition à un flux, vous créez un "flux conditionnel". Les flux conditionnels ne s'exécutent que lorsque la condition est évaluée à true. Vous pouvez associer autant de stratégies que vous le souhaitez à un flux conditionnel. Un flux conditionnel vous permet de créer des stratégies de traitement très spécialisées pour les messages de demande ou de réponse qui répondent à certains critères.

Par exemple, pour créer un flux qui ne s'exécute que lorsque le verbe de la requête est "GET" :

<Flows>
  <Flow name="ExecuteForGETs">
  <Condition>request.verb="GET"</Condition>
  </Flow>
</Flows>

Pour créer un flux pour les requêtes GET et un autre pour les requêtes POST, procédez comme suit :

<Flows>
  <Flow name="ExecuteForGETs">
  <Condition>request.verb="GET"</Condition>
  </Flow>
  <Flow name="ExecuteForPOSTs">
  <Condition>request.verb="POST"</Condition>
  </Flow>
</Flows>

Comme l'illustre l'exemple ci-dessous, vous pouvez appliquer la condition à l'étape de la règle elle-même. La condition suivante force l'application de la règle "VerifyApiKey" uniquement si un message est une requête POST.

<PreFlow name="PreFlow">
    <Request>
        <Step>
            <Condition>request.verb equals "POST"</Condition>
            <Name>VerifyApiKey</Name>
        </Step>
    </Request>
</PreFlow>

Une fois que vous avez défini de tels flux conditionnels, vous pouvez leur associer des règles qui activent un proxy d'API pour appliquer un ensemble de règles aux requêtes GET et un autre ensemble aux requêtes POST.

Pour obtenir des informations de référence complètes, consultez les ressources suivantes :

Exemple 1

L'exemple suivant montre un flux conditionnel unique nommé Convert-for-devices, configuré dans le flux de réponse ProxyEndpoint. Ajoutez la condition en tant qu'élément à l'entité à laquelle la condition s'applique. Dans cet exemple, la condition est un composant du flux. Par conséquent, le flux s'exécute chaque fois que l'instruction est évaluée à true.

<Flows>
  <Flow name="Convert-for-devices">
  <Condition>(request.header.User-Agent = "Mozilla")</Condition>
    <Response>
      <Step><Name>ConvertToJSON</Name></Step>
    </Response>
  </Flow>
</Flows>

Pour chaque requête reçue d'une application, Edge stocke les valeurs de tous les en-têtes HTTP présents sous forme de variables. Si la requête contient un en-tête HTTP appelé User-Agent, cet en-tête et sa valeur sont stockés sous forme de variable appelée request.header.User-Agent.

Compte tenu de la configuration ProxyEndpoint ci-dessus, Edge vérifie la valeur de la variable request.header.User-Agent pour voir si la condition est évaluée à true.

Si la condition est évaluée à true, c'est-à-dire que la valeur de la variable request.header.User-Agent est égale à Mozilla, le flux conditionnel s'exécute et la règle XMLtoJSON appelée ConvertToJSON est appliquée. Dans le cas contraire, le flux n'est pas exécuté et la réponse XML est renvoyée sans modification (au format XML) à l'application à l'origine de la requête.

Exemple 2

Prenons un exemple spécifique dans lequel vous devez convertir un message de réponse du format XML vers le format JSON, mais uniquement pour les appareils mobiles. Commencez par créer la règle qui convertit la réponse au format XML de l'API Weather vers le format JSON :

<XMLToJSON name="ConvertToJSON">
  <Options>
  </Options>
  <OutputVariable>response</OutputVariable>
  <Source>response</Source>
</XMLToJSON>

La configuration des règles ci-dessus indique au proxy d'API de récupérer le message de réponse, d'en effectuer une conversion de XML à JSON selon les paramètres par défaut, puis d'écrire le résultat dans le nouveau message de réponse. (Si vous convertissez un message request au format XML en JSON, il vous suffit de définir ces deux valeurs sur request.)

Étant donné que vous souhaitez convertir les réponses du format XML vers le format JSON, vous devez configurer un flux de réponse conditionnel pour effectuer la conversion. Par exemple, pour convertir toutes les réponses du format XML vers le format JSON avant qu'elles ne soient renvoyées à l'application cliente, configurez le flux de réponse ProxyEndpoint suivant.

<Flows>
  <Flow name="Convert-for-devices">
    <Response>
      <Step><Name>ConvertToJSON</Name></Step>
    </Response>
  </Flow>
</Flows>

Lorsque vous appelez l'API à l'aide de la requête standard, la réponse est au format JSON.

Toutefois, votre objectif est de convertir les rapports météorologiques au format JSON lorsque le client demandeur est un appareil mobile. Pour activer ce comportement dynamique, vous devez ajouter une instruction conditionnelle au flux.

Tester le flux conditionnel

Dans cet exemple de requête, l'en-tête HTTP User-Agent est défini sur Mozilla, ce qui a pour effet de rendre l'instruction conditionnelle égale à "true" et de lancer l'exécution du flux conditionnel Convert-for-devices.

$ curl -H "User-Agent:Mozilla" http://{org_name}-test.apigee.net/weather/forecastrss?w=12797282

ou, pour imprimer une version correctement formatée du code en Python, si disponible :

$ curl -H "User-Agent:Mozilla" http://{org_name}-test.apigee.net/weather/forecastrss?w=12797282 | python -mjson.tool

Exemple de réponse :

. . .

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

. . .

Une requête envoyée sans en-tête User-Agent ou avec une valeur différente de Mozilla entraînera une réponse au format XML.

$ curl http://{org_name}-test.apigee.net/weather/forecastrss?w=12797282

La réponse XML non modifiée est renvoyée.

Exemple de réponse :

<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" />

Correspondance de modèles

Cette section explique comment utiliser la correspondance de modèle avec des conditions dans un flux Apigee.

Opérateurs

Cette section explique comment utiliser les opérateurs de mise en correspondance de modèles suivants dans les instructions conditionnelles :

Correspond à

Commençons par examiner l'opérateur conditionnel "Matches" ou "~". Ces deux opérateurs sont identiques : la version en toutes lettres, "Matches", est considérée comme une option plus lisible.

Résumé : l'opérateur "Matches" vous offre deux possibilités. Soit faire correspondre la chaîne littéralement, soit au moyen d'un caractère générique comme "*". Comme vous pouvez le supposer, le caractère générique correspond à zéro ou plusieurs caractères. Voyons comment cela fonctionne.

Le code XML suivant montre une condition d'étape. Elle exécute la stratégie SomePolicy lorsque la condition est évaluée à "true". Dans cet exemple, nous testons la variable proxy.pathsuffix, une variable intégrée dans Edge qui stocke le suffixe de chemin de la requête. Toutefois, vous pouvez tester la valeur de toute variable de flux contenant une chaîne. Ainsi, dans ce cas, si le chemin de base de la requête entrante est /animals et que la requête est /animals/cat, le suffixe de chemin d'accès correspond à la chaîne littérale "/cat".

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix Matches "/cat")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

Question : quel suffixe de chemin d'accès au proxy entraîne l'exécution de "SomePolicy" ? Il n'y a qu'une seule possibilité.

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/cat

La règle s'exécute-t-elle ? Oui, car le suffixe du chemin d'accès du proxy correspond exactement à "/cat". Elle ne s'exécutera pas si le suffixe est /bat, /dog, "/" ou autre.

Soit maintenant cette instruction conditionnelle où nous utilisons le caractère générique "*" :

<Condition>(proxy.pathsuffix Matches "/*at")</Condition>

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/cat

La règle s'exécute-t-elle ? Oui, car le caractère générique correspond à n'importe quel caractère, et ""/cat" est une correspondance.

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/bat

La règle s'exécute-t-elle ? Oui, puisque le caractère générique correspond à n'importe quel caractère, "/bat" est une correspondance.

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/owl

La règle s'exécute-t-elle ? Absolument pas. Bien que le caractère générique corresponde à "o", les lettres "wl" ne sont pas prises en compte.

Maintenant, déplacez le caractère générique à la fin du suffixe :

<Condition>(proxy.pathsuffix Matches "/cat*")</Condition>

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/cat

La règle s'exécute-t-elle ? Oui, car le caractère générique correspond à zéro ou plusieurs caractères.

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/bat

La règle s'exécute-t-elle ? Non, "/bat" ne correspond pas.

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/cat123

La règle s'exécute-t-elle ? Oui, le caractère générique correspond à zéro ou plusieurs caractères. Par conséquent, "123" génère une correspondance.

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/cat/bird/mouse

La règle s'exécute-t-elle ? Oui, car le caractère générique correspond à zéro ou plusieurs caractères. Par conséquent, "/bird/mouse" génère une correspondance. Notez qu'une telle expression peut poser problème, car elle correspond à tous les éléments situés après les caractères littéraux !

Question : l'opérateur "Matches" est-il sensible à la casse ?

Oui. Supposons une condition comme celle-ci :

<Condition>(proxy.pathsuffix Matches "/*At")</Condition>

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/cat

La règle s'exécute-t-elle ? Non, le caractère générique correspond à n'importe quelle lettre (indépendamment du cas), mais "a" minuscule ne correspond pas à "A".

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/bAt

La règle s'exécute-t-elle ? Oui, la casse correspond.

Question : comment échapper les caractères avec l'opérateur "Matches" ?

Utilisez le caractère pourcentage "%" pour échapper les caractères réservés. Exemple :

<Condition>(proxy.pathsuffix Matches "/c%*at")</Condition>

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/cat

La règle s'exécute-t-elle ? Non, l'opérateur "Matches" recherche la chaîne littérale "c*at".

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/c*at

Question : la règle s'exécute-t-elle ?

Oui, bien que ce chemin d'accès soit légèrement inhabituel.

JavaRegex

Comme vous pouvez le voir, l'opérateur "Matches" est idéal pour les situations simples. Toutefois, vous pouvez utiliser un autre opérateur : l'opérateur "JavaRegex" ou "~~". Ces deux opérateurs sont les mêmes, mais "JavaRegex" est considéré comme plus lisible. Il s'appelle JavaRegex, car il permet la mise en correspondance des modèles d'expressions régulières. Edge suit les mêmes règles que les classes du package java.util.regex dans le langage Java. Le fonctionnement de l'opérateur "JavaRegex" est très différent de celui de l'opérateur "Matches". Il est donc important de ne pas les confondre !

Résumé : l'opérateur "JavaRegex" vous permet d'utiliser la syntaxe des expressions régulières dans les instructions conditionnelles.

Le code suivant montre une condition d'étape. Elle exécute la stratégie SomePolicy si la condition est évaluée à true. Dans cet exemple, nous testons la variable proxy.pathsuffix, une variable intégrée dans Edge qui stocke le suffixe de chemin de la requête. Si le chemin de base de la requête entrante est /animals et que la requête est /animals/cat, le suffixe de chemin d'accès correspond à la chaîne littérale "/cat".

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix JavaRegex "/cat")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

Question : quel suffixe de chemin d'accès au proxy entraîne l'exécution de "SomePolicy" ? Comme pour l'opérateur "Matches", il n'existe qu'une seule possibilité dans ce cas.

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/cat

La règle s'exécute-t-elle ? Oui, car le suffixe du chemin d'accès du proxy correspond exactement à "/cat". Elle ne s'exécutera pas si le suffixe est /bat, /dog, ou un autre élément.

Créons maintenant une expression régulière à l'aide du quantificateur "*". Ce quantificateur correspond à zéro ou à plusieurs caractères qui précèdent.

<Condition>(proxy.pathsuffix JavaRegex "/c*t")</Condition>

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/cat

La règle s'exécute-t-elle ? Non. Le quantificateur "*" correspond à zéro ou plusieurs occurrences du caractère qui précède, soit un caractère "c".

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/ccccct

La règle s'exécute-t-elle ? Oui, car le caractère générique correspond à  zéro ou plusieurs occurrences du caractère qui précède.

Nous utilisons ensuite le quantificateur "?", qui correspond une fois au caractère qui précède, ou n'y correspond pas du tout.

<Condition>(proxy.pathsuffix JavaRegex "/ca?t")</Condition>

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/cat

La règle s'exécute-t-elle ? Oui. Le quantificateur "?" correspond à zéro ou une occurrence du caractère qui précède, soit le caractère "a".

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/ct

La règle s'exécute-t-elle ? Oui. Le quantificateur "?" correspond à une occurrence du caractère qui précède ou n'y correspond pas. Dans ce cas, il n'y a pas de caractère "a", la condition est donc égale à "true".

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/caat

La règle s'exécute-t-elle ? Non. Le caractère quantificateur "?" correspond à une occurrence du caractère qui précède, qui est un "a".

Nous utilisons ensuite le style "[abc]" ou "regroupement" de l'expression régulière. Il correspond aux caractères "a", "b" ou "c".

<Condition>(proxy.pathsuffix JavaRegex "/[cbr]at")</Condition>

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/cat

La règle s'exécute-t-elle ? Oui. Nous utilisons ici des expressions régulières et l'expression "[cbr]" correspond à "c", "b", OU "r". Ces appels correspondent également :

GET http://artomatic-test.apigee.net/matchtest/bat

GET http://artomatic-test.apigee.net/matchtest/rat

Mais dans ce cas, il n'y pas de correspondance :

GET http://artomatic-test.apigee.net/matchtest/mat

Question : l'opérateur "JavaRegex" est-il sensible à la casse ?

Oui. Supposons une condition comme celle-ci :

<Condition>(proxy.pathsuffix JavaRegex "/ca?t")</Condition>

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/cat

La règle s'exécute-t-elle ? Oui, l'expression régulière correspond à zéro ou à une occurrence du caractère qui précède, qui est "a".

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/cAt

Question : la règle s'exécute-t-elle ?

Non, car le "A" majuscule ne correspond pas au "a" minuscule.

MatchesPath

L'opérateur MatchesPath peut également être spécifié comme suit : "~/". Il ressemble à peu près aux opérateurs Matches (~) et "JavaRegex" (~~). Cependant, "MatchesPath" est complètement différent.

Gardez à l'esprit que cet opérateur considère un chemin d'accès comme une série de parties. Par conséquent, si le chemin d'accès est /animals/cats/wild, vous pouvez le considérer comme étant constitué des parties "/animals", "/cats" et "/wild".

L'opérateur MatchesPath vous permet d'utiliser deux notations génériques : un astérisque unique (*) et un double astérisque (**). L'astérisque unique correspond à un élément de chemin d'accès. Le double astérisque correspond à un ou plusieurs éléments du chemin d'accès.

Prenons un exemple. Dans cet exemple, nous testons la variable proxy.pathsuffix, une variable intégrée dans Edge qui stocke le suffixe de chemin de la requête. Toutefois, vous pouvez tester la valeur de toute variable de flux contenant une chaîne.

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix MatchesPath "/animals/*")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

Question : quel suffixe de chemin d'accès au proxy entraîne l'exécution de "SomePolicy" ?

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/animals

Question : la règle s'exécute-t-elle ?

Non, car la condition nécessite un autre élément de chemin après "/animals", comme spécifié par "/*".

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/animals/

La règle s'exécute-t-elle ? Oui, le chemin d'accès comporte un autre élément de chemin d'accès (la partie située après "/animals/"), mais il est vide.

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/animals/cats

La règle s'exécute-t-elle ? Oui, car le chemin d'accès comporte clairement un élément ("/cats") après "/animals"

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/animals/cats/wild

Question : la règle s'exécute-t-elle ?

Non, car le seul astérisque ne correspond qu'à un seul élément du chemin et cette API comporte plusieurs éléments après "/animals".

Utilisons maintenant le double astérisque :

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix MatchesPath "/animals/**")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

Question : quel suffixe de chemin d'accès au proxy entraîne l'exécution de "SomePolicy" ?

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/animals

La règle s'exécute-t-elle ? Non, car la condition requiert au moins un élément de chemin à la suite, spécifié par "/**".

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/animals/

La règle s'exécute-t-elle ?

Oui, le chemin d'accès comporte un autre élément de chemin d'accès (la partie située après "/animals/"), mais il est vide.

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/animals/cats

La règle s'exécute-t-elle ?

Oui, car le chemin comporte au moins un élément situé après "/animals".

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/animals/cats/wild

La règle s'exécute-t-elle ?

Oui, car le chemin comporte plusieurs éléments qui suivent "/animals"

Astérisques mixtes

Vous pouvez combiner l'astérisque unique (*) et le double astérisque (**) pour affiner la correspondance avec le chemin d'accès.

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix MatchesPath "/animals/*/wild/**")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

Appel d'API :

Tous ces appels d'API génèrent une correspondance :

GET http://artomatic-test.apigee.net/matchtest/animals/cats/wild/

et

GET http://artomatic-test.apigee.net/matchtest/animals/dogs/wild/austrailian

et

GET http://artomatic-test.apigee.net/matchtest/animals/birds/wild/american/finches

Ressources liées aux API

Les services RESTful sont des collections de ressources d'API. Une ressource d'API est un fragment de chemin d'URI qui identifie une entité à laquelle les développeurs peuvent accéder en appelant votre API. Par exemple, si votre service fournit des rapports et des prévisions météorologiques, votre service de backend peut définir deux ressources d'API :

  • http://mygreatweatherforecast.com/reports
  • http://mygreatweatherforecast.com/forecasts

Lorsque vous créez un proxy d'API (comme indiqué dans la section Créer votre premier proxy d'API), vous créez au minimum une URL d'alias de base qui correspond à votre service de backend. Exemple :

URL de base du backend URL de proxy d'API nouvelle/équivalente
http://mygreatweatherforecast.com http://{your_org}-{environment}.apigee.net/mygreatweatherforecast

À ce stade, vous pouvez effectuer des appels d'API vers votre backend à l'aide de l'une ou l'autre des URL de base. Toutefois, lorsque vous utilisez l'URL de proxy d'API, la situation commence à s'intéresser.

Outre les analyses d'API qu'Edge commence à collecter lorsque vous utilisez le proxy d'API, les proxys vous permettent également de définir des flux conditionnels qui correspondent aux ressources de votre backend. En substance, "si un appel GET arrive à la ressource /reports, Edge doit faire quelque chose".

L'image suivante montre la différence de comportement entre deux URL qui accèdent finalement au même backend. L'une est l'URL de la ressource sans proxy, l'autre est un proxy d'API Edge avec un flux conditionnel vers la même ressource de backend. Vous trouverez ci-dessous une description détaillée des flux conditionnels.

Mappage des proxys d'API vers des ressources backend spécifiques

Avec une URL de proxy d'API mappée à l'URL de base du service de backend (lorsque vous créez le proxy), vous pouvez ajouter des flux conditionnels à des ressources spécifiques, telles que les ressources /reports et /forecasts mentionnées plus haut.

Supposons que vous souhaitiez qu'Edge "fait quelque chose" lorsque les appels arrivent dans les ressources /reports ou /forecasts. À ce stade, vous ne dites pas à Edge quoi faire, mais simplement qu'il doit écouter les appels à ces ressources. Pour ce faire, utilisez des conditions. Dans votre proxy d'API Edge, vous pouvez créer des flux conditionnels pour /reports et /forecasts. À des fins de concept, le fichier XML de proxy d'API suivant illustre ce à quoi pourraient ressembler ces conditions.

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

Ces conditions indiquent : "Lorsqu'une requête GET arrive avec /reports et /forecasts dans l'URL, Edge effectue ce que vous (le développeur de l'API) lui direz, via les stratégies que vous joignez à ces flux.

Voici maintenant un exemple indiquant à Edge ce qu'il faut faire lorsqu'une condition est remplie. Dans le fichier XML de proxy d'API suivant, lorsqu'une requête GET est envoyée à https://yourorg-test.apigee.net/mygreatweatherforecast/reports, Edge exécute la stratégie "XML-to-JSON-1" dans la réponse.

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

En plus de ces flux conditionnels facultatifs, chaque proxy d'API est également doté de deux flux par défaut : un <PreFlow> exécuté avant vos flux conditionnels et un <PostFlow> exécuté après. Ils sont utiles pour exécuter des règles lorsque tout appel est envoyé à un proxy d'API. Par exemple, si vous souhaitez valider la clé API d'une application à chaque appel, quelle que soit la ressource de backend accessible, vous pouvez placer une règle "Verify API Key" sur <PreFlow>. Pour plus d'informations sur les flux, consultez la section Configurer les flux.

Créer des flux conditionnels sur des ressources de backend

La définition de flux conditionnels sur des ressources de backend dans un proxy d'API est totalement facultative. Toutefois, ces flux conditionnels vous permettent d'appliquer une gestion et une surveillance précises.

Vous bénéficierez entre autres des avantages suivants :

  • Appliquer la gestion de manière à refléter la sémantique de votre modèle d'API
  • Appliquer des règles et un comportement scripté à des chemins d'accès de ressources individuels (URI)
  • Collecter des métriques détaillées pour les services d'analyse

Imaginons, par exemple, que vous deviez appliquer différents types de logique à votre backend /developers pour les ressources /apps.

Pour ce faire, ajoutez deux flux conditionnels dans votre proxy d'API : /developers et /apps.

Dans la vue "Develop" du volet de navigation de l'éditeur du proxy d'API, cliquez sur l'icône + à côté de la valeur par défaut de Proxy Endpoints.

Dans la fenêtre "New Conditional Flow", saisissez les configurations de clé suivantes :

  • Flow name : "Developers"
  • Condition Type : "Path"
  • Path : "/developers"

La condition est déclenchée (et les règles sont exécutées) si un appel comportant "/developers" à la fin de l'URI est envoyé au proxy.

Ajoutez maintenant un flux conditionnel pour /apps et supposons que vous souhaitez que la condition soit déclenchée à la fois par l'URI et par le verbe "POST" d'une requête. La configuration implique de définir les éléments suivants :

  • Flow Name : "Apps"
  • Condition Type (Type de condition) : chemin et verbe
  • Path : "/apps"
  • Verb : "POST"

La condition est déclenchée (et les règles sont exécutées) si un appel comportant "/apps" à la fin de l'URI et un verbe "POST" est envoyé au proxy.

Dans le volet de navigation, de nouveaux flux s'affichent pour Applications et Developers.

Sélectionnez l'un des flux pour afficher la configuration du flux conditionnel dans la vue Code de l'éditeur de proxy d'API :

<Flow name="Apps">
    <Description>Developer apps registered in Developer Services</Description>
    <Request/>
    <Response/>
    <Condition>(proxy.pathsuffix MatchesPath "/apps") and (request.verb = "POST")</Condition>
</Flow>

Comme vous pouvez le voir, les ressources de l'API sont simplement des flux conditionnels qui évaluent le chemin d'accès URI de la requête entrante. (La variable "proxy.pathsuffix" identifie l'URI de la requête qui suit le chemin "BasePath" configuré dans la configuration "ProxyEndpoint".)

Chaque ressource d'API que vous définissez est implémentée par un flux conditionnel dans le proxy d'API. (Consultez la section Configurer les flux.)

Une fois que vous avez déployé le proxy d'API dans l'environnement de test, la requête suivante :

http://{org_name}-test.apigee.net/{proxy_path}/apps

provoquera l'évaluation de la condition à "true", et ce flux, ainsi que toutes les règles associées, seront exécutés.

L'exemple de condition suivant utilise une expression régulière Java pour reconnaître les appels passés à la ressource /apps avec ou sans barre oblique finale (/apps ou /apps/**) :

<Condition>(proxy.pathsuffix JavaRegex "/apps(/?)") and (request.verb = "POST")</Condition>

Pour en savoir plus sur ce type de condition, consultez Comment établir une correspondance indépendamment ... dans la communauté Apigee.

Modéliser des URI hiérarchiques

Dans certains cas, vous aurez des ressources d'API hiérarchiques. Par exemple, l'API Services pour les développeurs fournit une méthode permettant de répertorier toutes les applications appartenant à un développeur. Le chemin de l'URI est le suivant :

/developers/{developer_email}/apps

Il peut arriver que des ressources à identifiant unique soient générées pour chaque entité d'une collection, qui est parfois annotée comme suit :

/genus/:id/species

Ce chemin d'accès s'applique également aux deux URI suivants :

/genus/18904/species
/genus/17908/species

Pour représenter cette structure dans une ressource d'API, vous pouvez utiliser des caractères génériques. Exemple :

/developers/*/apps
/developers/*example.com/apps
/genus/*/species

et traitera ces URI hiérarchiques en tant que ressources API de manière appropriée.

Dans certains cas, en particulier pour les API profondément hiérarchiques, vous pouvez simplement résoudre toutes les ressources sous un certain fragment d'URI. Pour ce faire, utilisez un caractère générique à deux astérisques dans votre définition de ressource. Par exemple, si vous définissez la ressource API suivante :
/developers/**

Cette ressource d'API résout les chemins d'accès URI suivants :

/developers/{developer_email}/apps
/developers/{developer_email}/keys
/developers/{developer_email}/apps/{app_id}/keys

Voici à quoi ressemblerait la condition de flux conditionnelle dans la définition du proxy d'API :

<Condition>(proxy.pathsuffix MatchesPath "/developers/**") and (request.verb = "POST")</Condition>

Autres exemples

Condition associée à "RouteRule"

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

Condition associée à une stratégie

<Step>
<!--the policy MaintenancePolicy only executes if the response status code is exactly 503-->
  <Condition>response.status.code = 503</Condition>
  <Name>MaintenancePolicy</Name>
</Step>

Flux conditionnel

<!-- 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>

Exemples d'opérateurs dans les conditions

Voici quelques exemples d'opérateurs utilisés pour créer des conditions :

  • 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

Exemple pratique : ignorer "/" à la fin d'un chemin d'accès

Les développeurs Edge souhaitent généralement gérer ces deux suffixes de chemin d'accès: "/cat" et "/cat/". En effet, certains utilisateurs ou clients peuvent appeler votre API avec la barre oblique supplémentaire à la fin du chemin d'accès. Vous devez donc pouvoir le gérer dans vos instructions conditionnelles. Ce cas d'utilisation précis a été abordé par la communauté Apigee.

Vous pouvez le faire sans utiliser d'expression régulière de la manière suivante :

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>((proxy.pathsuffix = "/cat") OR (proxy.pathsuffix = "/cat/")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

Cette option est intéressante. Elle est claire et lisible.

Vous pouvez faire la même chose avec les expressions régulières. Les parenthèses servent à regrouper la partie expression régulière de l'instruction, mais elles ne sont pas obligatoires.

<Condition>(proxy.pathsuffix JavaRegex "/cat(/?)"</Condition>

Appels d'API :

GET http://artomatic-test.apigee.net/matchtest/cat
or

GET http://artomatic-test.apigee.net/matchtest/cat/

La règle s'exécute-t-elle ? Oui. Notez que dans une expression régulière, le caractère "?" signifie: correspond à zéro ou à l'un des caractères précédents. Par conséquent, "/cat" et "/cat/" sont des correspondances.

Appel d'API :

GET http://artomatic-test.apigee.net/matchtest/cat/spotted

La règle s'exécute-t-elle ? Non. L'expression régulière correspond à zéro ou une seule occurrence du caractère qui précède, et rien d'autre n'est autorisé.

Dans tous les exemples de cette rubrique, nous expliquons comment mettre en correspondance l'une des variables de flux intégrées : "proxy.pathsuffix". Bon à savoir  : vous pouvez effectuer une correspondance de modèle sur n'importe quelle chaîne ou variable de flux arbitraire, qu'il s'agisse ou non d'une variable de flux intégrée telle que "proxy.pathsuffix".

Par exemple, si vous avez une condition qui teste une chaîne arbitraire, éventuellement une chaîne renvoyée dans une charge utile du backend, ou une chaîne renvoyée par une recherche de serveur d'authentification, vous pouvez utiliser des opérateurs correspondants pour la tester. Si vous utilisez JavaRegex, l'expression régulière est comparée à l'ensemble de la chaîne d'objet. Si l'objet est "abc" et que l'expression régulière est "[a-z]", il n'y a pas de correspondance, car "[a-z]" correspond exactement à un caractère alpha. L'expression "[a-z]+" fonctionne, tout comme "[a-z]*" et "[a-z]{3}.

Examinons un exemple concret. Supposons que le serveur d'authentification renvoie une liste de rôles sous la forme d'une chaîne délimitée par des virgules: "editor, author, user" (éditeur, auteur, invité).

Pour tester la présence du rôle d'éditeur, cette structure ne fonctionnera pas, car "editor" ne fait partie que de la chaîne entière.

<Condition>returned_roles ~~ "editor"</Condition>

Toutefois, cette structure fonctionnera :

<Condition>returned_roles ~~ ".*\beditor\b.*")</Condition>

Cela fonctionne, car elle tient compte des espaces entre les mots et de toute autre partie de la chaîne comportant le préfixe et le suffixe ".*".

Dans cet exemple, vous pouvez également tester le terme "editor" à l'aide de l'opérateur "Matches" :

<Condition>returned_roles ~~ "*editor*")</Condition>

Toutefois, si vous avez besoin d'une plus grande précision, "JavaRegex" est souvent mieux adapté.

Échapper les guillemets doubles dans les expressions JavaRegex

La syntaxe de la condition nécessite qu'une expression JavaRegex soit entourée de guillemets doubles. Par conséquent, si vous avez une expression régulière incluant des guillemets doubles, vous avez besoin d'un autre moyen de les mettre en correspondance. La réponse est Unicode. Par exemple, imaginons que vous transmettiez un en-tête contenant des guillemets doubles, comme suit :
 -H 'content-type:multipart/related; type="application/xop+xml"'
Si vous essayez de faire correspondre cet en-tête dans une condition Regex, vous obtenez une erreur de condition non valide, car l'expression inclut les guillemets doubles :
request.header.Content-Type ~~ "(multipart\/related)(; *type="application\/xop\+xml\")"
La solution consiste à remplacer les guillemets doubles basés sur ASCII par leur équivalent Unicode, \u0022. Par exemple, l'expression suivante est valide et produit le résultat attendu :
request.header.Content-Type ~~ "(multipart\/related)(; *type=\u0022application\/xop\+xml\u0022)"