Условия с переменными потока

Вы просматриваете документацию 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, тогда выражение оценивается как ложное.

Чтобы включить динамическое поведение, вы можете прикрепить Условия к потокам, шагам и правилам маршрута.

Когда вы присоединяете условие к Потоку, вы создаете «условный поток». Условные потоки выполняются только тогда, когда условие оценивается как истинное. Вы можете прикрепить к условному потоку столько политик, сколько захотите. Условный поток позволяет создавать узкоспециализированные правила обработки для сообщений запроса или ответа, которые соответствуют определенным критериям.

Например, чтобы создать поток, который выполняется только тогда, когда глагол запроса является 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 , чтобы увидеть, является ли условие истинным.

Если условие действительно оценивается как true, то есть значение переменной 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 только в том случае, если запрашивающим клиентом является мобильное устройство . Чтобы включить такое динамическое поведение, необходимо добавить в поток 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.

Операторы

В этом разделе описывается, как использовать следующие операторы сопоставления с образцом в условных операторах:

Матчи

Давайте сначала рассмотрим условный оператор «Совпадения» или «~». Эти два оператора одинаковы: английская версия «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

Политика выполняется? Нет, подстановочный знак соответствует любой букве (независимо от регистра), но строчная буква «а» не соответствует букве «А».

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

Как видите, оператор «Совпадения» отлично подходит для простых ситуаций. Но вы можете использовать другой оператор: «JavaRegex» или «~~». Это один и тот же оператор, за исключением того, что JavaRegex считается более читабельным. Он называется JavaRegex, поскольку позволяет сопоставлять шаблоны регулярных выражений, а Edge следует тем же правилам, что и классы в пакете java.util.regex на языке Java. Принцип работы оператора JavaRegex сильно отличается от оператора Matches, поэтому важно не путать их!

Описание: Оператор JavaRegex позволяет использовать синтаксис регулярных выражений в условных операторах.

Следующий код показывает условие Step. Он выполняет политику SomePolicy, если условие оценивается как true. В этом примере мы тестируем переменную 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

Политика выполняется? Да, регулярное выражение соответствует нулю или одному из предшествующих символов, то есть «а».

API-вызов:

GET http://artomatic-test.apigee.net/matchtest/cAt

Вопрос: выполняется ли политика?

Нет, потому что заглавная «А» не соответствует строчной «а».

МатчиПуть

Оператор 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, что делать, а просто говорите, что он должен прослушивать вызовы к этим ресурсам. Вы делаете это с условиями. В прокси-сервере 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 приложения при каждом вызове, независимо от того, к какому внутреннему ресурсу осуществляется доступ, вы можете поместить политику проверки ключа API в <PreFlow> . Дополнительные сведения о потоках см. в разделе Настройка потоков .

Создание условных потоков для серверных ресурсов

Определение условных потоков для внутренних ресурсов в прокси-сервере API совершенно необязательно. Однако эти условные потоки дают вам возможность применять детальное управление и мониторинг.

Вы сможете:

  • Применяйте управление таким образом, чтобы оно отражало семантику вашей модели API.
  • Применяйте политики и сценарии поведения к отдельным путям ресурсов (URI).
  • Сбор детальных показателей для служб аналитики.

Например, представьте, что вам нужно применить разные типы логики к ресурсам серверной части /разработчикам/приложениям.

Для этого вы добавляете в свой прокси API два условных потока: /developers и /apps .

В представлении «Разработка» панели «Навигатор» редактора прокси-сервера API щелкните значок + рядом со значением по умолчанию в конечных точках прокси.

В окне «Новый условный поток» вы должны ввести следующие ключевые конфигурации:

  • Название потока : Разработчики
  • Тип условия : Путь
  • Путь : /разработчики

Условие будет активировано (и политики будут выполнены), если на прокси-сервер будет отправлен вызов с /developers в конце URI.

Теперь добавьте условный поток для /apps и предположим, что вы хотите, чтобы условие запускалось как для URI, так и для команды 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 служб разработчиков предоставляет метод для перечисления всех приложений, принадлежащих разработчику. Путь 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, вот так. Круглые скобки используются для группировки регулярной части оператора, но они не являются обязательными.

<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, содержащее двойные кавычки, вам нужен альтернативный способ их сопоставления. Ответ: Юникод. Например, предположим, что вы передаете заголовок, содержащий двойные кавычки, как показано ниже:
 -H 'content-type:multipart/related; type="application/xop+xml"'
Если вы попытаетесь сопоставить этот заголовок с условием регулярного выражения, вы получите ошибку «Неверное условие», поскольку выражение содержит двойные кавычки:
request.header.Content-Type ~~ "(multipart\/related)(; *type="application\/xop\+xml\")"
Решение состоит в том, чтобы заменить двойные кавычки на основе ASCII их эквивалентом в Юникоде \u0022 . Например, следующее выражение допустимо и дает ожидаемый результат:
request.header.Content-Type ~~ "(multipart\/related)(; *type=\u0022application\/xop\+xml\u0022)"