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 :
- Opérateur
Matches
: mise en correspondance de modèles simple - Opérateur "JavaRegex" : contrôle plus précis de la mise en correspondance
- Opérateur
MatchesPath
: correspondance de fragment de chemin
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
etGET
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.
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 :
- Sélectionnez l'onglet Développer dans l'éditeur de proxy.
- 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%" />
- Cliquez sur le bouton + au-dessus du volet Response (Réponse).
- 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
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. - Nom du flux :
- 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 verbePOST
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 verbePOST
est envoyé au proxy. - Nom du flux :
Les flux ajoutés s'affichent dans le volet Response (Réponse) :
É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.
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
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
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.
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)"