Conditions avec variables de flux

Cette page s'applique à Apigee et à Apigee hybrid.

Consultez la documentation d'Apigee Edge.

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 en utilisant la syntaxe suivante :

<Condition>VARIABLE_NAME OPERATOR "VALUE"</Condition>

Exemple :

<Condition>request.verb = "GET"</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 faire correspondre des expressions régulières JavaRegex avec 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 renseigne une longue liste de variables associées à des éléments tels que l'heure du système, les informations réseau de l'application, les en-têtes HTTP des messages, la configuration du proxy d'API, l'exécution de stratégies, 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 Content-type header, 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.

Imaginons que vous deviez créer une instruction conditionnelle qui ne s'applique que 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>

Apigee utilise une telle déclaration pour évaluer les conditions. L'exemple ci-dessus renvoie la valeur "true" si le verbe HTTP associé à la requête est GET. Si le verbe HTTP associé à la requête est POST, l'instruction renvoie la valeur "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 un 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 renvoie la valeur 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, Apigee 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 de "ProxyEndpoint" ci-dessus, Apigee vérifie la valeur de la variable request.header.User-Agent pour déterminer si la condition est égale à "true".

Si la condition renvoie true, c'est-à-dire que la valeur de la variable request.header.User-Agent est Mozilla, le flux conditionnel s'exécute et la stratégie 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://example.com/weather/forecastrss?w=12797282

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

curl -H "User-Agent:Mozilla" http://example.com/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://example.com/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 :

Correspondances

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

Résumé : l'opérateur Matches vous offre deux possibilités. Correspondre à la chaîne littéralement ou effectuer une correspondance avec *. Comme vous pourriez vous y attendre, 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 Apigee, qui stocke le suffixe de chemin d'accès 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 du chemin est 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://example.com/matchtest/cat

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

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://example.com/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://example.com/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://example.com/matchtest/owl

La règle s'exécute-t-elle ? Certainement pas ; même si le caractère générique correspond à o, les lettres wl ne sont pas mises en correspondance.

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

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

Appel d'API :

GET http://example.com/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://example.com/matchtest/bat

La règle s'exécute-t-elle ? Non, /bat n'est pas une correspondance.

Appel d'API :

GET http://example.com/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://example.com/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://example.com/matchtest/cat

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

Appel d'API :

GET http://example.com/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 de pourcentage % pour échapper les caractères réservés. Exemple :

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

Appel d'API :

GET http://example.com/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://example.com/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 se nomme "JavaRegex", car il autorise la mise en correspondance des modèles d'expression régulière, et Apigee suit les mêmes règles que les classes du package java.util.regex du langage Java. Le fonctionnement de l'opérateur JavaRegex est très différent de l'opérateur Matches. Il est donc important de ne pas confondre les deux !

Résumé : l'opérateur JavaRegex vous permet d'utiliser la syntaxe d'expression régulière 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 Apigee, qui stocke le suffixe de chemin d'accès 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 du chemin est 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://example.com/matchtest/cat

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

Nous allons maintenant créer une expression régulière à l'aide du quantificateur *. Ce quantificateur correspond à zéro ou plusieurs des caractères précédents.

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

Appel d'API :

GET http://example.com/matchtest/cat

La règle s'exécute-t-elle ? Non. Le quantificateur * correspond à zéro ou à plusieurs des caractères précédents, qui correspondent à un caractère c.

Appel d'API :

GET http://example.com/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 précédent, ou pas du tout.

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

Appel d'API :

GET http://example.com/matchtest/cat

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

Appel d'API :

GET http://example.com/matchtest/ct

La règle s'exécute-t-elle ? Oui. Le quantificateur ? correspond à un ou aucun du caractère précédent. Dans ce cas, il n'existe pas de caractère a, et la condition renvoie donc la valeur true.

Appel d'API :

GET http://example.com/matchtest/caat

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

Nous utilisons ensuite le style [abc] ou le regroupement d'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://example.com/matchtest/cat

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

GET http://example.com/matchtest/bat

GET http://example.com/matchtest/rat

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

GET http://example.com/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://example.com/matchtest/cat

La règle s'exécute-t-elle ? Oui, l'expression régulière correspond à zéro ou à un du caractère précédent, soit a.

Appel d'API :

GET http://example.com/matchtest/cAt

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

Non, car la lettre majuscule A ne correspond pas à la lettre minuscule a.

MatchesPath

Vous pouvez également spécifier l'opérateur MatchesPath comme suit : ~/. Il semble un peu semblable 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 composé 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.

Voyons un exemple. Dans cet exemple, nous testons la variable proxy.pathsuffix, une variable intégrée dans Apigee, qui stocke le suffixe de chemin d'accès 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://example.com/matchtest/animals

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

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

Appel d'API :

GET http://example.com/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 après /animals/), mais il est simplement vide.

Appel d'API :

GET http://example.com/matchtest/animals/cats

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

Appel d'API :

GET http://example.com/matchtest/animals/cats/wild

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

Non, car l'astérisque unique ne correspond qu'à un seul élément de 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://example.com/matchtest/animals

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

Appel d'API :

GET http://example.com/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 après /animals/), mais il est simplement vide.

Appel d'API :

GET http://example.com/matchtest/animals/cats

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

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

Appel d'API :

GET http://example.com/matchtest/animals/cats/wild

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

Oui, car le chemin d'accès comporte plusieurs éléments placés après /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://example.com/matchtest/animals/cats/wild/

et

GET http://example.com/matchtest/animals/dogs/wild/austrailian

et

GET http://example.com/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://example.com/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.

En plus des analyses d'API qu'Apigee commence à collecter lorsque vous utilisez le proxy d'API, les proxys vous permettent également de définir des flux conditionnels mappés aux ressources de votre backend. En substance, si un appel GET arrive à la ressource /reports, Apigee devrait 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 Apigee avec un flux conditionnel à la même ressource backend. Vous trouverez ci-dessous une description détaillée des flux conditionnels.

Concernant l'URL du proxy de l'API Apigee doté d'un flux conditionnel, la réponse convertit le code XML au format JSON et collecte les données analytiques.

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 vouliez qu'Apigee effectue une action lorsque les appels sont transmis aux ressources /reports ou /forecasts. À ce stade, vous ne demandez pas à Apigee de faire ce qu'il faut faire, mais vous devez simplement écouter les appels à ces ressources. Pour ce faire, utilisez des conditions. Dans votre proxy d'API Apigee, 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>

Les conditions sont les suivantes : Lorsqu'une requête GET est effectuée avec /reports et /forecasts dans l'URL, Apigee effectue toutes les opérations que vous (le développeur de l'API) lui indiquez, via les règles que vous appliquez à ces flux.

Voici un exemple où il est indiqué à Apigee ce qu'il doit faire lorsqu'une condition est remplie. Dans le fichier XML de proxy d'API ci-dessous, lorsqu'une requête GET est envoyée à https://example.com/mygreatweatherforecast/reports, Apigee exécute la règle 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

Par exemple, imaginons que vous devez appliquer différents types de logique à vos ressources /developers à /apps de backend.

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

Nouvel éditeur de proxys

Pour ajouter un flux conditionnel, procédez comme suit :

  1. Sélectionnez l'onglet Développer dans l'éditeur de proxy.
  2. Sélectionnez Points de terminaison du proxy > Par défaut dans le volet de gauche.

    Par défaut dans le volet de gauche." 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. Cliquez sur le bouton + au-dessus du volet Response (Réponse).

    Bouton permettant d'ajouter un flux conditionnel

  4. Dans la boîte de dialogue Add Conditional Flow (Ajouter un flux conditionnel), saisissez les configurations suivantes :
    • Nom du flux : Developers
    • Type de condition : Path
    • Chemin d'accès : /developers

    Boîte de dialogue "Ajouter un flux conditionnel".

    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.

  5. 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 :
    • Nom du flux : Apps
    • Type de condition : Path and Verb
    • Chemin d'accès : /apps
    • Verbe : 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.

Les flux ajoutés s'affichent dans le volet Response (Réponse) :

Boîte de dialogue "Ajouter un flux conditionnel".

Éditeur de proxy classique

Dans le volet Développer du volet Navigateur de l'éditeur de proxy d'API, cliquez sur à côté de par défaut dans Points de terminaison proxy.

Lorsque vous placez le pointeur sur le signe plus situé à côté de la valeur par défaut, le texte de l'info-bulle indique "Add New Flow".

Dans la fenêtre Nouveau flux conditionnel, saisissez les configurations de clé suivantes :

  • Nom du flux : Developers
  • Type de condition : Path
  • Chemin d'accès : /developers

Dans le volet "New Conditional Flow", un flux nommé "Developers" est configuré avec la description "App developers registered with Developer Services".

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 :

  • Nom du flux : Apps
  • Type de condition : Path and Verb
  • Chemin d'accès : /apps
  • Verbe : POST

Dans le volet "New Conditional Flow", un flux nommé "Apps" est configuré avec la description "Developer apps registered in Developer Services".

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 Navigateur, de nouveaux flux s'affichent pour Applications et Developers.

Les nouveaux flux "Applications" et les "Developers" sont affichés dans le volet de navigation sous "Proxy Endpoints".

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 mise en œuvre 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://example.com/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 la section Comment effectuer une correspondance avec ou sans "/" de fin... 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 pour les applications de développement permet 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

Ceux-ci permettent de résoudre les URI hiérarchiques comme des ressources d'API en conséquence.

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 d'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 Apigee souhaitent généralement gérer les deux suffixes de chemin d'accès suivants : /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, et vous devez être en mesure de gérer cela dans vos instructions conditionnelles. Ce cas d'utilisation exact a été décrit dans la section Comment effectuer une correspondance avec ou sans "/" de fin dans l'URL....

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://example.com/matchtest/cat
or
GET http://example.com/matchtest/cat/

La règle s'exécute-t-elle ? Oui. Notez que dans une expression régulière, le caractère ? signifie : faire correspondre à 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://example.com/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é.

Mise en correspondance des chaînes arbitraires avec "JavaRegex"

Dans tous les exemples de cette rubrique, nous expliquons comment mettre en correspondance l'une des variables de flux intégrées : proxy.pathsuffix. Il est bon à savoir que vous pouvez effectuer une correspondance de modèles 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 à la chaîne de caractères entière. 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 alphanumérique. 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 forme de chaîne délimitée par des virgules : editor, author, guest.

Pour tester la présence du rôle d'éditeur, cette construction ne fonctionnera pas, car editor ne fait partie que d'une partie de la chaîne.

<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 editor avec 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 placée entre guillemets doubles. Par conséquent, si vous disposez d'une expression régulière incluant des guillemets doubles, vous avez besoin d'une autre méthode pour les faire correspondre. La réponse est Unicode. Par exemple, disons que vous transmettez dans 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 à une condition d'expression régulière, vous obtiendrez une erreur Invalid Condition, car l'expression inclut les guillemets doubles :

request.header.Content-Type ~~ "(multipart\/related)(; *type="application\/xop\+xml\")"

La solution consiste à remplacer les guillemets doubles 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)"