Вы просматриваете документацию 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 использует такое выражение для оценки условий. Приведённый выше пример оценивается как «истина», если HTTP-команда, связанная с запросом, — GET. Если HTTP-команда, связанная с запросом, — POST, то выражение оценивается как «ложь».
Чтобы включить динамическое поведение, вы можете прикрепить условия к потокам, шагам и правилам маршрутизации.
Прикрепляя условие к потоку, вы создаёте «условный поток». Условные потоки выполняются только при выполнении условия. К условному потоку можно прикрепить любое количество политик. Условный поток позволяет создавать узкоспециализированные правила обработки запросов и ответов, соответствующие определённым критериям.
Например, чтобы создать поток, который выполняется только в том случае, если глаголом запроса является 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. Добавьте Condition как элемент к сущности, к которой применяется условие. В этом примере условие является компонентом потока. Следовательно, поток будет выполняться всякий раз, когда выражение принимает значение true.
<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 , то выполняется условный поток (Flow) и применяется политика XMLtoJSON, называемая ConvertToJSON . В противном случае поток (Flow) не выполняется, и XML-ответ возвращается неизменённым (в формате XML) запрашивающему приложению.
Пример 2
Рассмотрим конкретный пример, в котором вам нужно преобразовать ответное сообщение из XML в JSON, но только для мобильных устройств. Сначала создайте политику, которая будет преобразовывать ответ от Weather API в формате XML в 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 только в том случае, если запрашивающим клиентом является мобильное устройство . Чтобы реализовать такое динамическое поведение, необходимо добавить условный оператор в Flow.
Тестирование условного потока
В этом примере запроса заголовок HTTP User-Agent установлен на Mozilla , в результате чего условный оператор оценивается как true и выполняется условный поток 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.
Операторы
В этом разделе описывается, как использовать следующие операторы сопоставления с шаблонами в условных операторах:
- Оператор сопоставления : простое сопоставление с образцом
- Оператор JavaRegex : более точный контроль над сопоставлением
- Оператор MatchesPath : сопоставление фрагментов пути
Спички
Давайте сначала рассмотрим условный оператор «Matches» или «~». Эти два оператора идентичны — английская версия «Matches» считается более удобной для чтения.
Краткое описание: Оператор «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 " вернет совпадение. Обратите внимание, что подобное выражение может привести к проблемам, поскольку оно соответствует всему после литеральных символов!
Вопрос: Чувствителен ли оператор Matches к регистру?
Да. Предположим, у вас такое состояние:
<Condition>(proxy.pathsuffix Matches "/*At")</Condition>
API-вызов:
GET http://artomatic-test.apigee.net/matchtest/cat
Выполняется ли политика? Нет, подстановочный знак соответствует любой букве (независимо от регистра), но строчная «a» не соответствует «A».
API-вызов:
GET http://artomatic-test.apigee.net/matchtest/bAt
Политика выполняется? Да, всё соответствует.
Вопрос: Как экранировать символы с помощью оператора Matches?
Используйте символ процента «%» для экранирования зарезервированных символов. Например:
<Condition>(proxy.pathsuffix Matches "/c%*at")</Condition>
API-вызов:
GET http://artomatic-test.apigee.net/matchtest/cat
Выполняется ли политика? Нет, оператор Matches ищет строку «c*at».
API-вызов:
GET http://artomatic-test.apigee.net/matchtest/c*at
Вопрос: Выполняется ли политика?
Да, этот путь, хоть и немного необычный, совпадает.
JavaRegex
Как видите, оператор «Matches» отлично подходит для простых ситуаций. Но вы можете использовать другой оператор — «JavaRegex» или «~~». Это один и тот же оператор, за исключением того, что JavaRegex считается более читабельным. Он называется JavaRegex, потому что позволяет сопоставлять шаблоны с регулярными выражениями, и Edge следует тем же правилам, что и классы из пакета java.util.regex в языке Java. Принцип работы оператора JavaRegex сильно отличается от принципа работы оператора Matches, поэтому важно не путать их!
Краткое описание: Оператор «JavaRegex» позволяет использовать синтаксис регулярных выражений в условных операторах.
Следующий код демонстрирует условие Step. Политика 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
Выполняется ли политика? Да. Квантификатор « ? » соответствует одному или ни одному из предшествующих символов. В данном случае символ «a» отсутствует, поэтому условие выполняется.
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 /
Выполняется ли политика? Да, в пути есть ещё один элемент path (часть после « /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, прокси-серверы также позволяют определять условные потоки, которые сопоставляются с ресурсами на вашем бэкенде. По сути, «если к ресурсу /reports поступает вызов GET, Edge должен что-то сделать».
На следующем изображении показана разница в поведении двух URL-адресов, которые в конечном итоге обращаются к одному и тому же бэкенду. Один из них — URL-адрес ресурса без прокси-сервера, другой — прокси-сервер Edge API с условным потоком к тому же бэкенд-ресурсу. Мы подробнее опишем условные потоки ниже.

Как прокси-серверы API сопоставляются с определенными внутренними ресурсами
С помощью URL-адреса прокси-сервера API, сопоставленного с базовым URL-адресом внутренней службы (при создании прокси-сервера), вы можете добавлять условные потоки к определенным ресурсам, например ресурсам /reports и /forecasts упомянутым ранее.
Допустим, вам нужно, чтобы Edge «что-то делал» при поступлении вызовов к ресурсам /reports или /forecasts . На этом этапе вы не сообщаете Edge, что делать, а лишь указываете ему, что он должен прослушивать вызовы к этим ресурсам. Это делается с помощью условий. В вашем прокси-сервере API Edge вы можете создать условные потоки для /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 приложения при каждом вызове, независимо от того, к какому внутреннему ресурсу осуществляется доступ, вы можете добавить политику проверки ключа API к <PreFlow> . Подробнее о потоках см. в разделе «Настройка потоков» .
Создание условных потоков для внутренних ресурсов
Определение условных потоков к внутренним ресурсам в API-прокси совершенно необязательно. Однако эти условные потоки позволяют применять детальное управление и мониторинг.
Вы сможете:
- Применяйте управление таким образом, чтобы оно отражало семантику вашей модели API.
- Применять политики и сценарии поведения к отдельным путям ресурсов (URI)
- Собирайте детальные метрики для аналитических служб
Например, представьте, что вам необходимо применить различные типы логики к ресурсам бэкэнда /developers to /apps.
Для этого вам нужно добавить два условных потока в ваш API-прокси: /developers и /apps .
В представлении «Разработка» на панели «Навигатор» редактора прокси-сервера API щелкните значок + рядом со значением по умолчанию в конечных точках прокси-сервера.
![]()
В окне «Новый условный поток» необходимо ввести следующие ключевые конфигурации:
- Название потока : Разработчики
- Тип состояния : Путь
- Путь : /developers

Условие будет запущено (и политики будут выполнены), если вызов будет отправлен на прокси-сервер с /developers в конце URI.
Теперь добавьте условный поток для /apps и предположим, что вы хотите, чтобы условие срабатывало как для URI, так и для команды POST в запросе. Конфигурация включает в себя следующие настройки:
- Название потока : Приложения
- Тип условия : Путь и глагол
- Путь : /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. Например, API Developer Services предоставляет метод для получения списка всех приложений, принадлежащих разработчику. Путь 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 = 500 -
request.uri MatchesPath "/*/statuses/**" -
request.queryparam.q0 NotEquals 10
Практический пример: игнорировать «/» в конце пути.
Разработчики Edge обычно хотят обрабатывать оба суффикса пути: " /cat " и " /cat/ ". Это связано с тем, что некоторые пользователи или клиенты могут вызывать ваш API с дополнительным слешем в конце пути, и вам необходимо иметь возможность обрабатывать это в условных операторах. Именно этот вариант использования обсуждался в сообществе Apigee .
При желании вы можете добиться этого без использования Regex, вот так:
<PreFlow name="PreFlow">
<Request>
<Step>
<Condition>((proxy.pathsuffix = "/cat") OR (proxy.pathsuffix = "/cat/")</Condition>
<Name>SomePolicy</Name>
</Step>
</Request>
<Response/>
</PreFlow>Это хороший вариант. Он понятен и легко читается.
Однако то же самое можно сделать и с помощью Regex, вот так. Скобки используются для группировки части Regex в операторе, но они не обязательны.
<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», а регулярное выражение — «[az]», совпадения нет, поскольку «[az]» соответствует ровно одному буквенному символу. Выражение «[az]+» работает, как и «[az]*» и «[az]{3}».
Рассмотрим конкретный пример. Предположим, сервер аутентификации возвращает список ролей в виде строки, разделённой запятыми: «редактор, автор, гость».
Для проверки наличия роли редактора эта конструкция не подойдет, поскольку «редактор» — это только часть всей строки.
<Condition>returned_roles ~~ "editor"</Condition>
Однако эта конструкция будет работать:
<Condition>returned_roles ~~ ".*\beditor\b.*")</Condition>
Это работает, потому что учитывает переносы слов и любые другие части строки с префиксом и суффиксом .*.
В этом примере вы также можете проверить наличие слова «редактор» с помощью оператора Matches:
<Condition>returned_roles ~~ "*editor*")</Condition>
Однако в случаях, когда вам нужна большая точность, JavaRegex часто оказывается лучшим выбором.
Экранирование двойных кавычек в выражениях JavaRegex
Синтаксис Condition требует, чтобы выражение JavaRegex было заключено в двойные кавычки. Поэтому, если у вас есть выражение Regex, включающее двойные кавычки, вам нужен альтернативный способ их сопоставления. Решение — Unicode. Например, предположим, что вы передаёте заголовок, включающий двойные кавычки, например:-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)"