Вы просматриваете документацию по Apigee Edge.
Перейдите к документации по Apigee X. Информация
Условные операторы – это распространенная управляющая структура во всех языках программирования. Как и язык программирования, конфигурация прокси-сервера 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, то утверждение оценивается как ложное.
Чтобы включить динамическое поведение, вы можете прикрепить условия к потокам, шагам и правилам маршрутизации.
Если вы добавите условие в Flow, то создадите условный Flow. Условные процессы выполняются только в том случае, если условие истинно. К условному потоку можно прикрепить любое количество правил. Условный поток позволяет создавать специализированные правила обработки для запросов или ответов, соответствующих определенным критериям.
Например, чтобы создать Flow, который выполняется только при использовании глагола 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, но только для мобильных устройств. Сначала создайте правило, которое будет преобразовывать ответ Weather API в формате XML в формат JSON:
<XMLToJSON name="ConvertToJSON"> <Options> </Options> <OutputVariable>response</OutputVariable> <Source>response</Source> </XMLToJSON>
Приведенная выше конфигурация правил указывает прокси-серверу API взять сообщение ответа, преобразовать его из XML в JSON с настройками по умолчанию, а затем записать результат в новое сообщение ответа. (Если вы преобразуете сообщение request из 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.
Операторы
В этом разделе рассказывается, как использовать в условных операторах следующие операторы сопоставления с образцом:
- Оператор "Соответствует": простое сопоставление с образцом.
- Оператор JavaRegex позволяет более точно управлять сопоставлением.
- Оператор MatchesPath: сопоставление фрагментов пути
Соответствует
Сначала рассмотрим условный оператор "Совпадает" или "~". Эти два оператора одинаковы, но английская версия ("Соответствует") считается более понятной.
Краткий ответ. Оператор "Соответствует" позволяет использовать два варианта. Строка должна совпадать с указанной в точности или с учетом подстановочного знака "*", который может соответствовать любому количеству символов. Вот как это работает.
.Ниже приведен пример условия 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 позволяет использовать синтаксис регулярных выражений в условных операторах.
Ниже приведен пример кода с условием 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? Как и в случае с оператором "Соответствует", здесь возможен только один вариант.
Вызов 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
Вопрос. Выполняются ли правила?
Нет, потому что заглавная буква "A" не соответствует строчной "a".
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, прокси-серверы также позволяют определять условные потоки, которые сопоставляются с ресурсами на вашем сервере. По сути, это означает: "Если в ресурс /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)
- Как собирать подробные показатели для сервисов Аналитики
Предположим, вам нужно применить разные типы логики к ресурсам backend/developers и /apps.
Для этого добавьте в прокси-сервер API два условных потока: /developers и /apps.
В режиме разработки в области навигации редактора прокси-сервера API нажмите на значок плюса рядом с пунктом default в разделе Proxy Endpoints (Конечные точки прокси).
![]()
В окне "Новый условный поток" нужно ввести следующие ключевые конфигурации:
- Название процесса: "Разработчики"
- Тип условия: путь.
- Путь: /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. Например, 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>
Это работает, потому что учитываются переносы слов и любые другие части строки с префиксом и суффиксом .*.
В этом примере вы также можете проверить наличие роли "Редактор", используя оператор "Соответствует":
<Condition>returned_roles ~~ "*editor*")</Condition>
Однако в случаях, когда требуется более высокая точность, JavaRegex часто является лучшим выбором.
Как экранировать двойные кавычки в выражениях JavaRegex
Синтаксис условия требует, чтобы выражение 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)"