Вы просматриваете документацию по Apigee Edge.
Перейдите к
документации по Apigee X. info
Условные операторы – это распространенная управляющая структура во всех языках программирования. Как и язык программирования, конфигурация прокси-сервера API поддерживает условные операторы для потоков, правил, шагов и правил маршрутизации. Определяя условные операторы, вы определяете динамическое поведение для своего API. Такое динамическое поведение позволяет, например, преобразовывать XML в JSON только для мобильных устройств или направлять на URL серверной части на основе типа контента или HTTP-команды сообщения запроса.
В этой статье рассказывается, как использовать условия для динамического применения функций управления API во время выполнения без написания кода.
Как настроить условные операторы
Условное поведение реализуется в прокси-серверах API с помощью сочетания условий и переменных. Условное выражение создается с помощью элемента Condition. Ниже приведен пример пустого условия:
<Condition></Condition>
Чтобы создать условное выражение, добавьте условный оператор и переменную в следующую структуру:
<Condition>{variable.name}{operator}{"value"}</Condition>
Поддерживаются следующие условные операторы: = (равно), != (не равно) и > (больше). Для удобства чтения вы также можете написать условные выражения в виде текста: equals, notequals, greaterthan.
При работе с путями URI можно использовать ~/ или MatchesPath. Вы также можете сопоставлять регулярные выражения JavaRegex с помощью оператора ~~.
Условия используются для определения условных потоков прокси-сервера API к ресурсам API бэкенда, как описано в разделе Создание условных потоков к ресурсам API бэкенда. Полный список условий приведен в справочнике.
Переменные
Условия оценивают значения переменных. Переменная – это свойство HTTP-транзакции, выполняемой прокси-сервером API, или свойство конфигурации самого прокси-сервера API. Каждый раз, когда прокси-сервер API получает запрос от приложения, Apigee Edge заполняет длинный список переменных, связанных с такими вещами, как системное время, сетевая информация приложения, HTTP-заголовки сообщений, конфигурация прокси-сервера API, выполнение политик и т. д. Это создает богатый контекст, который можно использовать для настройки условных операторов.
В переменных всегда используется точечная нотация. Например, HTTP-заголовки в сообщении запроса доступны как переменные с названием request.header.{header_name}. Чтобы оценить заголовок Content-type, можно использовать переменную request.header.Content-type. Например, request.header.Content-type = "application/json" указывает, что тип контента запроса должен быть JSON.
Представьте, что вам нужно создать условное выражение, которое будет вызывать применение правила только в том случае, если сообщение запроса является GET. Чтобы создать условие, которое оценивает HTTP-глагол запроса, создайте условный оператор ниже. Переменная в этом условии – request.verb. Значение переменной – GET. Оператор – =.
<Condition>request.verb = "GET"</Condition>
<Condition>request.verb equals "GET"</Condition>
Edge использует такое выражение для оценки условий. Приведенный выше пример возвращает значение True, если с запросом связан HTTP-метод GET. Если с запросом связан HTTP-метод POST, то выражение принимает значение false.
Чтобы включить динамическое поведение, вы можете прикрепить условия к потокам, шагам и правилам маршрутизации.
Если вы добавите условие в поток, то получите условный поток. Условные потоки выполняются, только если условие истинно. К условному потоку можно прикрепить любое количество правил. Условный поток позволяет создавать узкоспециализированные правила обработки для сообщений запросов или ответов, соответствующих определенным критериям.
Например, чтобы создать поток, который выполняется, только когда глагол запроса – GET:
<Flows> <Flow name="ExecuteForGETs"> <Condition>request.verb="GET"</Condition> </Flow> </Flows>
Чтобы создать один поток для GET, а другой – для POST:
<Flows> <Flow name="ExecuteForGETs"> <Condition>request.verb="GET"</Condition> </Flow> <Flow name="ExecuteForPOSTs"> <Condition>request.verb="POST"</Condition> </Flow> </Flows>
Как показано в примере ниже, условие можно применить к самому шагу правила. Следующее условие приводит к тому, что правило VerifyApiKey применяется только в том случае, если сообщение запроса является POST.
<PreFlow name="PreFlow">
<Request>
<Step>
<Condition>request.verb equals "POST"</Condition>
<Name>VerifyApiKey</Name>
</Step>
</Request>
</PreFlow>Определив такие условные потоки, вы можете прикрепить к ним политики, позволяющие прокси-серверу API применять один набор политик для GET-запросов, а другой набор политик для запросов POST.
Подробную справочную информацию можно найти в следующих ресурсах:
Пример 1
В примере ниже показан один условный поток с названием Convert-for-devices, настроенный в потоке ответов ProxyEndpoint. Добавьте условие в качестве элемента к объекту, к которому оно применяется. В этом примере условие является компонентом потока.
Поэтому процесс будет выполняться каждый раз, когда условие будет истинным.
<Flows>
<Flow name="Convert-for-devices">
<Condition>(request.header.User-Agent = "Mozilla")</Condition>
<Response>
<Step><Name>ConvertToJSON</Name></Step>
</Response>
</Flow>
</Flows>Для каждого запроса, полученного от приложения, Edge сохраняет значения всех HTTP-заголовков в виде переменных. Если запрос содержит HTTP-заголовок User-Agent, то этот заголовок и его значение сохраняются в переменной request.header.User-Agent.
Учитывая приведенную выше конфигурацию ProxyEndpoint, Edge проверяет значение переменной request.header.User-Agent, чтобы определить, является ли условие истинным.
Если условие выполняется, то есть значение переменной request.header.User-Agent равно Mozilla, то выполняется условный поток и применяется правило XMLtoJSON с названием ConvertToJSON. Если нет, то поток не выполняется, а ответ XML возвращается в запрашивающее приложение без изменений (в формате XML).
Пример 2
Рассмотрим конкретный пример, в котором вам нужно преобразовать ответное сообщение из XML в JSON, но только для мобильных устройств. Сначала создайте правило, которое будет преобразовывать ответ в формате XML от Weather API в формат JSON:
<XMLToJSON name="ConvertToJSON"> <Options> </Options> <OutputVariable>response</OutputVariable> <Source>response</Source> </XMLToJSON>
Приведенная выше конфигурация правила указывает прокси-серверу API взять ответное сообщение, преобразовать его из XML в JSON с настройками по умолчанию, а затем записать результат в новое ответное сообщение. Если вы преобразуете сообщение запроса из XML в JSON, просто задайте для обоих этих значений request.
Поскольку вы хотите преобразовать ответы из XML в JSON, вам нужно настроить условный поток ответов для выполнения преобразования. Например, чтобы преобразовать все ответы из XML в JSON перед их возвратом в клиентское приложение, настройте следующий поток ответов ProxyEndpoint.
<Flows>
<Flow name="Convert-for-devices">
<Response>
<Step><Name>ConvertToJSON</Name></Step>
</Response>
</Flow>
</Flows>При вызове API с помощью стандартного запроса ответ форматируется в JSON.
Однако ваша цель – преобразовывать отчеты о погоде в формат JSON, только когда запрашивающий клиент является мобильным устройством. Чтобы включить такое динамическое поведение, необходимо добавить в поток условный оператор.
Протестируйте процесс с условиями
В этом примере запроса HTTP-заголовок User-Agent имеет значение Mozilla, поэтому условное выражение оценивается как истинное и выполняется условный поток Convert-for-devices.
$ curl -H "User-Agent:Mozilla" http://{org_name}-test.apigee.net/weather/forecastrss?w=12797282
или, если доступен Python, используйте автоформатирование:
$ curl -H "User-Agent:Mozilla" http://{org_name}-test.apigee.net/weather/forecastrss?w=12797282 | python -mjson.tool
Пример ответа:
. . .
"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"
}
]
}
. . .Если запрос отправлен без заголовка User-Agent или с другим значением, отличным от Mozilla, то ответ будет в формате XML.
$ curl http://{org_name}-test.apigee.net/weather/forecastrss?w=12797282
Возвращается неизмененный XML-ответ.
Пример ответа:
<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" />
Соответствие шаблону
В этом разделе описывается, как использовать сопоставление с образцом с условиями в потоке Apigee.
Операторы
В этом разделе описывается, как использовать в условных операторах следующие операторы сопоставления с шаблоном:
- Оператор matches: простое сопоставление с шаблоном
- Оператор JavaRegex: более точный контроль над сопоставлением.
- Оператор MatchesPath: сопоставление фрагментов пути
Соответствует
Сначала рассмотрим условный оператор "Соответствует" (~). Эти два оператора одинаковы, но английский вариант Matches считается более понятным.
Краткие сведения. Оператор "Соответствует" предоставляет две возможности. Вы можете указать точную строку или использовать подстановочный знак (*), который соответствует любому количеству символов. Вот как это работает.
Ниже приведен пример XML-кода с условием Step. Если условие выполняется, то применяется правило SomePolicy. В этом примере мы тестируем переменную proxy.pathsuffix – встроенную переменную в Edge, в которой хранится суффикс пути запроса. Однако вы можете протестировать значение любой переменной потока, содержащей строку. Таким образом, если базовый путь входящего запроса – /animals, а сам запрос – /animals/cat, то суффиксом пути будет строка "/cat".
<PreFlow name="PreFlow">
<Request>
<Step>
<Condition>(proxy.pathsuffix Matches "/cat")</Condition>
<Name>SomePolicy</Name>
</Step>
</Request>
<Response/>
</PreFlow>Вопрос. Какой суффикс пути прокси-сервера приведет к выполнению SomePolicy? Есть только один вариант.
Вызов API:
GET http://artomatic-test.apigee.net/matchtest/cat
Выполняется ли правило? Да, потому что суффикс пути прокси-сервера точно соответствует "/cat". Если суффикс будет иметь вид /bat, /dog, / или любой другой, то тег не сработает.
Теперь рассмотрим условное выражение, в котором используется подстановочный знак *:
<Condition>(proxy.pathsuffix Matches "/*at")</Condition>
Вызов API:
GET http://artomatic-test.apigee.net/matchtest/cat
Выполняется ли правило? Да, потому что подстановочный знак соответствует любому символу, а "/cat – это совпадение.
Вызов API
GET http://artomatic-test.apigee.net/matchtest/bat
Выполняется ли правило? Да, поскольку подстановочный знак соответствует любому символу, "/bat" является совпадением.
Вызов API
GET http://artomatic-test.apigee.net/matchtest/owl
Выполняется ли правило? Нет, потому что подстановочный знак соответствует только части o, а часть wl не совпадает.
Теперь переместим подстановочный знак в конец суффикса:
<Condition>(proxy.pathsuffix Matches "/cat*")</Condition>
Вызов API:
GET http://artomatic-test.apigee.net/matchtest/cat
Выполняется ли правило? Да, потому что подстановочный знак соответствует любому количеству любых символов.
Вызов API
GET http://artomatic-test.apigee.net/matchtest/bat
Выполняется ли правило? Нет, "/bat" не подходит.
Вызов API:
GET http://artomatic-test.apigee.net/matchtest/cat123
Выполняется ли правило? Да, подстановочный знак соответствует любому количеству любых символов, поэтому 123 подходит.
Вызов API:
GET http://artomatic-test.apigee.net/matchtest/cat/bird/mouse
Выполняется ли правило? Да, потому что подстановочный знак соответствует любому количеству любых символов, поэтому /bird/mouse подходит. Обратите внимание, что такое выражение может привести к проблемам, поскольку оно соответствует всему, что идет после буквенных символов.
Учитывается ли регистр при использовании оператора "Соответствует"?
Да. Допустим, у вас есть следующее условие:
<Condition>(proxy.pathsuffix Matches "/*At")</Condition>
Вызов API:
GET http://artomatic-test.apigee.net/matchtest/cat
Выполняется ли правило? Нет, подстановочный знак соответствует любой букве (независимо от регистра), но строчная буква "а" не соответствует заглавной "А".
Вызов API:
GET http://artomatic-test.apigee.net/matchtest/bAt
Выполняется ли правило? Да, регистр совпадает.
Как экранировать символы при использовании оператора "Соответствует"?
Для экранирования зарезервированных символов используйте знак процента (%). Пример:
<Condition>(proxy.pathsuffix Matches "/c%*at")</Condition>
Вызов API:
GET http://artomatic-test.apigee.net/matchtest/cat
Выполняется ли правило? Нет, оператор "Соответствует" ищет точную строку "c*at".
Вызов API:
GET http://artomatic-test.apigee.net/matchtest/c*at
Вопрос. Будет ли применена политика?
Да, этот путь, хотя и немного необычный, совпадает.
JavaRegex
Как видите, оператор "Соответствует" отлично подходит для простых ситуаций. Однако вы можете использовать другой оператор – JavaRegex или ~~. Это один и тот же оператор, но JavaRegex считается более удобным для чтения. Оно называется JavaRegex, потому что позволяет сопоставлять шаблоны регулярных выражений, а Edge следует тем же правилам, что и классы в пакете java.util.regex на языке Java. Принцип работы оператора JavaRegex сильно отличается от принципа работы оператора Matches, поэтому важно не путать их.
Общие сведения. Оператор JavaRegex позволяет использовать синтаксис регулярных выражений в условных операторах.
В следующем коде показано условие шага. Если условие выполняется, выполняется правило SomePolicy. В этом примере мы тестируем переменную proxy.pathsuffix, встроенную переменную в Edge, в которой хранится суффикс пути запроса. Если базовый путь входящего запроса – /animals, а сам запрос – /animals/cat, то суффиксом пути будет строка "/cat".
<PreFlow name="PreFlow">
<Request>
<Step>
<Condition>(proxy.pathsuffix JavaRegex "/cat")</Condition>
<Name>SomePolicy</Name>
</Step>
</Request>
<Response/>
</PreFlow>Вопрос. Какой суффикс пути прокси-сервера приведет к выполнению SomePolicy? Как и в случае с оператором Matches, здесь возможен только один вариант.
Вызов API:
GET http://artomatic-test.apigee.net/matchtest/cat
Выполняется ли правило? Да, потому что суффикс пути прокси-сервера точно соответствует "/cat". Если суффикс будет другим, например /bat или /dog, то тег не сработает.
Теперь давайте создадим регулярное выражение с помощью квантификатора "*". Этот квантификатор соответствует нулю или более предшествующих символов.
<Condition>(proxy.pathsuffix JavaRegex "/c*t")</Condition>
Вызов API:
GET http://artomatic-test.apigee.net/matchtest/cat
Выполняется ли правило? Нет! Квантификатор "*" соответствует нулю или более предыдущих символов, то есть "c".
Вызов API
GET http://artomatic-test.apigee.net/matchtest/ccccct
Выполняется ли правило? Да, потому что подстановочный знак соответствует нулю или более предшествующих символов.
Затем мы используем квантификатор ?, который соответствует предыдущему символу один раз или ни разу.
<Condition>(proxy.pathsuffix JavaRegex "/ca?t")</Condition>
Вызов API:
GET http://artomatic-test.apigee.net/matchtest/cat
Выполняется ли правило? Да. Квантификатор ? соответствует нулю или одному вхождению предыдущего символа, то есть a.
Вызов API
GET http://artomatic-test.apigee.net/matchtest/ct
Выполняется ли правило? Да. Квантификатор "?" соответствует одному или ни одному из предыдущих символов. В данном случае символа "а" нет, поэтому условие оценивается как истинное.
Вызов API
GET http://artomatic-test.apigee.net/matchtest/caat
Выполняется ли правило? Нет. Квантификатор "?" соответствует одному предшествующему символу, то есть a.
Затем мы используем регулярное выражение "[abc]" или стиль группировки. Соответствует символам a, b или c.
<Condition>(proxy.pathsuffix JavaRegex "/[cbr]at")</Condition>
Вызов API:
GET http://artomatic-test.apigee.net/matchtest/cat
Выполняется ли правило? Да. В этом примере мы используем регулярные выражения. Выражение [cbr] соответствует символам "c", "b" или "r". Следующие вызовы также соответствуют правилу:
GET http://artomatic-test.apigee.net/matchtest/bat
GET http://artomatic-test.apigee.net/matchtest/rat
Но это не совпадение:
GET http://artomatic-test.apigee.net/matchtest/mat
Учитывается ли регистр при использовании оператора JavaRegex?
Да. Допустим, у вас есть следующее условие:
<Condition>(proxy.pathsuffix JavaRegex "/ca?t")</Condition>
Вызов API:
GET http://artomatic-test.apigee.net/matchtest/cat
Выполняется ли правило? Да, регулярное выражение соответствует нулю или одному из предыдущих символов, то есть "a".
Вызов API:
GET http://artomatic-test.apigee.net/matchtest/cAt
Вопрос. Будет ли применено правило?
Нет, потому что заглавная буква "А" не соответствует строчной букве "а".
MatchesPath
Оператор MatchesPath также можно указать как "~/". Он похож на операторы Matches (~) и JavaRegex (~~). Но MatchesPath – это совсем другое.
Помните, что этот оператор рассматривает путь как последовательность частей. Например, путь /animals/cats/wild состоит из частей /animals, /cats и /wild.
Оператор MatchesPath позволяет использовать два подстановочных знака: одну звездочку (*) и две (**). Одна звездочка соответствует одному элементу пути. Две звездочки соответствуют одному или нескольким элементам пути.
Рассмотрим пример. В этом примере мы тестируем переменную proxy.pathsuffix, встроенную переменную в Edge, в которой хранится суффикс пути запроса. Однако вы можете проверить значение любой переменной потока, содержащей строку.
<PreFlow name="PreFlow">
<Request>
<Step>
<Condition>(proxy.pathsuffix MatchesPath "/animals/*")</Condition>
<Name>SomePolicy</Name>
</Step>
</Request>
<Response/>
</PreFlow>Вопрос. Какой суффикс пути прокси-сервера приведет к выполнению SomePolicy?
Вызов API:
GET http://artomatic-test.apigee.net/matchtest/animals
Вопрос. Будет ли применено правило?
Нет, потому что условие требует ещё одного элемента пути после /animals, как указано в /*.
Вызов API:
GET http://artomatic-test.apigee.net/matchtest/animals/
Выполняется ли правило? Да, в пути есть ещё один элемент (часть после /animals/), но он пустой.
Вызов API
GET http://artomatic-test.apigee.net/matchtest/animals/cats
Выполняется ли правило? Да, потому что в пути есть элемент (/cats), который идет после /animals.
Вызов API
GET http://artomatic-test.apigee.net/matchtest/animals/cats/wild
Вопрос. Будет ли применено правило?
Нет, потому что одна звездочка соответствует только одному элементу пути, а в этом API после /animals их несколько.
Теперь используем двойную звездочку:
<PreFlow name="PreFlow">
<Request>
<Step>
<Condition>(proxy.pathsuffix MatchesPath "/animals/**")</Condition>
<Name>SomePolicy</Name>
</Step>
</Request>
<Response/>
</PreFlow>Вопрос. Какой суффикс пути прокси-сервера приведет к выполнению SomePolicy?
Вызов API:
GET http://artomatic-test.apigee.net/matchtest/animals
Выполняется ли правило? Нет, потому что условие требует хотя бы одного следующего элемента пути, указанного в /**.
Вызов API:
GET http://artomatic-test.apigee.net/matchtest/animals/
Выполняется ли правило?
Да, у пути есть ещё один элемент (часть после /animals/), но он пустой.
Вызов API
GET http://artomatic-test.apigee.net/matchtest/animals/cats
Выполняется ли правило?
Да, потому что в пути есть хотя бы один элемент, который идет после /animals.
Вызов API
GET http://artomatic-test.apigee.net/matchtest/animals/cats/wild
Выполняется ли правило?
Да, потому что в пути есть несколько элементов, которые следуют за /animals.
Смешивание звездочек
Вы можете использовать комбинации из одной (*) и двух (**) звездочек, чтобы точнее настроить сопоставление путей.
<PreFlow name="PreFlow">
<Request>
<Step>
<Condition>(proxy.pathsuffix MatchesPath "/animals/*/wild/**")</Condition>
<Name>SomePolicy</Name>
</Step>
</Request>
<Response/>
</PreFlow>Вызов API:
Все эти вызовы API будут соответствовать:
GET http://artomatic-test.apigee.net/matchtest/animals/cats/wild/
и
GET http://artomatic-test.apigee.net/matchtest/animals/dogs/wild/austrailian
и
GET
http://artomatic-test.apigee.net/matchtest/animals/birds/wild/american/finches
Ресурсы API
Сервисы RESTful – это наборы ресурсов API. Ресурс API – это фрагмент пути URI, который идентифицирует объект, доступный разработчикам при вызове вашего API. Например, если ваш сервис предоставляет сводки и прогнозы погоды, то в бэкенд-службе можно определить два ресурса API:
- http://mygreatweatherforecast.com/reports
- http://mygreatweatherforecast.com/forecasts
При создании прокси-сервера API (как показано в разделе Создание первого прокси-сервера API) вы как минимум создаете псевдоним базового URL, который сопоставляется с вашей бэкенд-службой. Пример:
| Базовый URL бэкенда | Новый или эквивалентный URL прокси-сервера API |
|---|---|
| http://mygreatweatherforecast.com | http://{your_org}-{environment}.apigee.net/mygreatweatherforecast |
Теперь вы можете выполнять вызовы API к своему бэкенду, используя любой из базовых URL. Но когда вы используете URL прокси-сервера API, все становится интереснее.
Помимо аналитики API, которую Edge начинает собирать при использовании прокси-сервера API, прокси-серверы также позволяют определять условные потоки, которые сопоставляются с ресурсами в вашем бэкенде. По сути, "Если вызов GET поступает в ресурс /reports, Edge должен что-то сделать".
На изображении ниже показана разница в поведении двух URL, которые в конечном итоге обращаются к одному и тому же бэкенду. Один – это URL ресурса без прокси, а другой – прокси-сервер Edge API с условным потоком к тому же ресурсу бэкенда. Ниже мы подробнее расскажем об условных процессах.

Как прокси-серверы API сопоставляются с определенными ресурсами бэкенда
Если URL прокси-сервера API сопоставлен с базовым URL бэкенд-службы (при создании прокси-сервера), вы можете добавить условные потоки к определенным ресурсам, например к ресурсам /reports и /forecasts, упомянутым выше.
Предположим, вы хотите, чтобы Edge выполнял определенные действия при поступлении вызовов к ресурсам /reports или /forecasts. На этом этапе вы не указываете Edge, что делать, а только сообщаете, что нужно ожидать вызовов этих ресурсов. Для этого используются условия. В прокси-сервере Edge API можно создать условные потоки для /reports и /forecasts. Ниже приведен пример XML-кода прокси-сервера API, который показывает, как могут выглядеть эти условия.
<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>Эти условия означают следующее: "Когда поступает GET-запрос с /reports и /forecasts в URL, Edge выполняет все, что вы (разработчик API) ему указываете, в соответствии с правилами, которые вы прикрепляете к этим потокам.
Вот пример того, как указать Edge, что делать при выполнении условия. В следующем XML-коде прокси-сервера API, когда GET-запрос отправляется на https://yourorg-test.apigee.net/mygreatweatherforecast/reports, Edge выполняет правило XML-to-JSON-1 в ответе.
<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>Помимо этих необязательных условных потоков, каждый прокси-сервер API также поставляется с двумя потоками по умолчанию: <PreFlow>, выполняемым до условных потоков, и <PostFlow>, выполняемым после условных потоков. Они полезны для выполнения правил при любом вызове прокси-сервера API. Например, если вы хотите проверять ключ API приложения при каждом вызове, независимо от того, к какому ресурсу бэкенда осуществляется доступ, вы можете поместить правило Verify API Key в <PreFlow>. Подробнее о настройке потоков…
Как создать условные потоки для ресурсов бэкенда
Определять условные потоки к ресурсам бэкенда в прокси-сервере API необязательно. Однако эти условные потоки дают вам возможность применять детальное управление и мониторинг.
Вы сможете:
- Применяйте управление таким образом, чтобы оно отражало семантику вашей модели API.
- Применение правил и скриптов к отдельным путям ресурсов (URI)
- Сбор подробных показателей для сервисов аналитики
Например, вам нужно применить разные типы логики к ресурсам /developers и /apps.
Для этого добавьте в прокси-сервер API два условных потока: /developers и /apps.
В представлении Develop (Разработка) на панели навигации редактора прокси-сервера API нажмите на значок плюса рядом с пунктом default (по умолчанию) в разделе Proxy Endpoints (Конечные точки прокси-сервера).
![]()
В окне New Conditional Flow (Новый условный поток) введите следующие основные конфигурации:
- Название процесса: Разработчики
- Тип условия: Path (Путь).
- Путь: /developers

Условие будет активировано (и правила будут выполнены), если вызов отправлен на прокси-сервер с /developers в конце URI.
Теперь добавьте условный поток для /apps и предположите, что вы хотите, чтобы условие срабатывало как для URI, так и для глагола POST в запросе. Для этого нужно задать следующие параметры:
- Название процесса: Apps.
- Тип условия: Path and Verb (Путь и глагол).
- Путь: /apps.
- Глагол: POST.

Условие будет активировано (и правила будут выполнены), если вызов отправлен на прокси-сервер с /apps в конце URI и глаголом POST.
На панели навигации вы увидите новые процессы для приложений и разработчиков.

Выберите один из потоков, чтобы посмотреть его конфигурацию в редакторе прокси-сервера 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>
Как видите, ресурсы API – это просто условные потоки, которые оценивают путь URI входящего запроса. (Переменная proxy.pathsuffix идентифицирует URI запроса, который следует за BasePath, заданным в конфигурации ProxyEndpoint.)
Каждый ресурс API, который вы определяете, реализуется условным потоком в прокси-сервере API. Подробнее о настройке потоков…
После развертывания прокси-сервера API в тестовой среде следующий запрос:
http://{org_name}-test.apigee.net/{proxy_path}/appsусловие будет выполнено, и этот поток вместе со всеми связанными правилами будет выполнен.
В следующем примере условия используется регулярное выражение Java, чтобы распознавать вызовы, сделанные к ресурсу /apps с косой чертой в конце или без нее (/apps или /apps/**):
<Condition>(proxy.pathsuffix JavaRegex "/apps(/?)") and (request.verb = "POST")</Condition>
Подробнее об этом типе условий рассказывается в статье о сопоставлении независимо от регистра в сообществе Apigee.
Моделирование иерархических URI
В некоторых случаях у вас будут иерархические ресурсы API. Например, Developer Services API предоставляет метод для получения списка всех приложений, принадлежащих разработчику. Путь URI:
/developers/{developer_email}/appsУ вас могут быть ресурсы, в которых для каждого объекта в коллекции генерируется уникальный идентификатор. Иногда это обозначается следующим образом:
/genus/:id/species
Этот путь в равной степени относится к следующим двум URI:
/genus/18904/species /genus/17908/species
Чтобы представить эту структуру в ресурсе API, можно использовать подстановочные знаки. Пример:
/developers/*/apps
/developers/*example.com/apps
/genus/*/species
будет правильно разрешать эти иерархические URI как ресурсы API.
В некоторых случаях, особенно для API со сложной иерархией, может потребоваться разрешить все, что находится ниже определенного фрагмента URI. Для этого используйте в определении ресурса подстановочный знак в виде двойной звездочки. Например, если вы определите следующий ресурс API:/developers/**
Этот ресурс API будет разрешать следующие пути URI:
/developers/{developer_email}/apps
/developers/{developer_email}/keys
/developers/{developer_email}/apps/{app_id}/keysВот как будет выглядеть условие условного потока в определении прокси-сервера API:
<Condition>(proxy.pathsuffix MatchesPath "/developers/**") and (request.verb = "POST")</Condition>
Другие примеры
Условие, прикрепленное к 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>
Условие, прикрепленное к правилу
<Step> <!--the policy MaintenancePolicy only executes if the response status code is exactly 503--> <Condition>response.status.code = 503</Condition> <Name>MaintenancePolicy</Name> </Step>
Условный поток
<!-- 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>
Примеры операторов в условиях
Вот несколько примеров операторов, используемых для создания условий:
request.header.content-type = "text/xml"request.header.content-length < 4096 && request.verb = "PUT"response.status.code = 404 || response.status.code = 500request.uri MatchesPath "/*/statuses/**"request.queryparam.q0 NotEquals 10
Пример: игнорирование косой черты в конце пути
Разработчики Edge обычно хотят обрабатывать оба этих суффикса пути: "/cat" и "/cat/". Это связано с тем, что некоторые пользователи или клиенты могут вызывать ваш API с дополнительной косой чертой в конце пути, и вам необходимо иметь возможность обрабатывать это в своих условных операторах. Этот пример использования обсуждался в сообществе Apigee.
Если вы не хотите использовать регулярные выражения, то можете сделать следующее:
<PreFlow name="PreFlow">
<Request>
<Step>
<Condition>((proxy.pathsuffix = "/cat") OR (proxy.pathsuffix = "/cat/")</Condition>
<Name>SomePolicy</Name>
</Step>
</Request>
<Response/>
</PreFlow>Это хороший вариант. Он четкий и разборчивый.
Однако вы можете сделать то же самое с помощью регулярного выражения, например: Круглые скобки используются для группировки регулярного выражения, но они не обязательны.
<Condition>(proxy.pathsuffix JavaRegex "/cat(/?)"</Condition>
Вызовы API
GET http://artomatic-test.apigee.net/matchtest/cat
or
GET http://artomatic-test.apigee.net/matchtest/cat/
Выполняется ли правило? Да. Обратите внимание, что в регулярном выражении символ ? означает, что предыдущий символ может отсутствовать или присутствовать один раз. Поэтому совпадениями будут и /cat, и /cat/.
Вызов API:
GET http://artomatic-test.apigee.net/matchtest/cat/spotted
Выполняется ли правило? Нет. Регулярное выражение соответствует нулю или только одному вхождению предыдущего символа, и ничего другого не допускается.
Сопоставление произвольных строк с помощью JavaRegex
Во всех примерах в этой теме мы показываем, как сопоставить одну из встроенных переменных потока: proxy.pathsuffix. Полезно знать, что сопоставление с шаблоном можно выполнять для любой произвольной строки или переменной потока, независимо от того, является ли она встроенной переменной потока, такой как proxy.pathsuffix.
Например, если у вас есть условие, которое проверяет произвольную строку, возможно, строку, возвращенную в полезной нагрузке бэкенда, или строку, возвращенную из поиска на сервере аутентификации, вы можете использовать операторы сопоставления для ее проверки. Если вы используете JavaRegex, регулярное выражение будет сравниваться со всей строкой темы. Если тема – "abc", а регулярное выражение – "[a-z]", совпадений не будет, поскольку "[a-z]" соответствует ровно одному буквенному символу. Выражение [a-z]+ работает так же, как [a-z]* и [a-z]{3}.
Рассмотрим конкретный пример. Предположим, что сервер аутентификации возвращает список ролей в виде строки с разделителями-запятыми: "editor, author, guest".
Для проверки наличия роли редактора эта конструкция не будет работать, поскольку "editor" – это только часть всей строки.
<Condition>returned_roles ~~ "editor"</Condition>
Однако следующая конструкция будет работать:
<Condition>returned_roles ~~ ".*\beditor\b.*")</Condition>
Это работает, потому что учитываются пробелы и другие части строки с префиксом и суффиксом .*.
В этом примере вы также можете проверить наличие слова "editor" с помощью оператора Matches:
<Condition>returned_roles ~~ "*editor*")</Condition>
Однако в случаях, когда требуется большая точность, JavaRegex часто является лучшим выбором.
Экранирование двойных кавычек в выражениях JavaRegex
Синтаксис условия требует, чтобы выражение JavaRegex было заключено в двойные кавычки. Поэтому, если у вас есть регулярное выражение, включающее двойные кавычки, вам нужен альтернативный способ их сопоставления. Ответ – Юникод. Например, вы передаете заголовок, содержащий двойные кавычки:-H 'content-type:multipart/related; type="application/xop+xml"'
request.header.Content-Type ~~ "(multipart\/related)(; *type="application\/xop\+xml\")"
\u0022. Например, следующее выражение допустимо и дает ожидаемый результат:
request.header.Content-Type ~~ "(multipart\/related)(; *type=\u0022application\/xop\+xml\u0022)"