Condições com variáveis de fluxo

Você está vendo a documentação do Apigee Edge.
Acesse a documentação da Apigee X.
informações

Instruções condicionais são uma estrutura de controle comum em todas as linguagens de programação. Como uma linguagem de programação, a configuração de proxy da API aceita instruções condicionais para fluxos, políticas, etapas e RouteRules. Ao definir instruções condicionais, você define o comportamento dinâmico da sua API. Esse comportamento dinâmico permite executar ações como converter XML em JSON apenas para dispositivos móveis ou rotear para um URL de back-end com base no tipo de conteúdo ou verbo HTTP da mensagem de solicitação.

Este tópico mostra como usar condições para aplicar dinamicamente os recursos de gerenciamento de API no ambiente de execução, sem escrever código.

Configurar instruções condicionais

O comportamento condicional é implementado em proxies da API por meio de uma combinação de conditions e conditions. Uma instrução condicional é criada usando um elemento Condition. Veja a seguir uma condição vazia:

<Condition></Condition>

Para criar uma instrução condicional, adicione um operador condicional e uma variável para criar a seguinte estrutura:

<Condition>{variable.name}{operator}{"value"}</Condition>

Os operadores condicionais compatíveis incluem = (igual a), != (não igual) e > (maior que). Para facilitar a leitura, você também pode escrever as condicionais como texto: equals, notequals, greaterthan.

Ao trabalhar com caminhos de URI, você pode usar ~/ ou MatchesPath. Você também pode corresponder expressões regulares JavaRegex com o operador ~~.

As condições são usadas para definir os fluxos condicionais do proxy da API para recursos da API do back-end, descritos em Criar fluxos condicionais para recursos da API de back-end. Para ver uma lista completa de condicionais, consulte Referência de condições.

Variáveis

As condições funcionam com a avaliação dos valores de variáveis. Uma variável é uma propriedade de uma transação HTTP executada por um proxy de API ou uma propriedade de configuração de proxy da própria API. Sempre que um proxy de API recebe uma solicitação de um app, o Apigee Edge preenche uma longa lista de variáveis associadas a itens como horário do sistema, informações de rede do app, cabeçalhos HTTP em mensagens, configuração do proxy de API, execuções de políticas e assim por diante. Isso cria um contexto avançado que pode ser usado para configurar instruções condicionais.

As variáveis sempre usam uma notação pontilhada. Por exemplo, os cabeçalhos HTTP na mensagem de solicitação estão disponíveis como variáveis chamadas request.header.{header_name}. Portanto, para avaliar o cabeçalho do tipo de conteúdo, use a variável request.header.Content-type. Por exemplo, request.header.Content-type = "application/json" indica que o tipo de conteúdo da solicitação precisa ser JSON.

Imagine que você precisa criar uma instrução condicional que fará com que uma política seja aplicada somente quando uma mensagem de solicitação for GET. Para criar uma condição que avalie o verbo HTTP de uma solicitação, crie a instrução condicional abaixo. A variável nessa condição é request.verb. O valor da variável é GET. O operador é =.

<Condition>request.verb = "GET"</Condition>
Você também pode usar:
<Condition>request.verb equals "GET"</Condition>

O Edge usa essa instrução para avaliar as condições. O exemplo acima será avaliado como verdadeiro se o verbo HTTP associado à solicitação for GET. Se o verbo HTTP associado à solicitação for POST, a instrução será avaliada como falsa.

Para ativar o comportamento dinâmico, você pode anexar condições a fluxos, etapas e RouteRules.

Ao anexar uma condição a um fluxo, você cria um "fluxo condicional". Os fluxos condicionais são executados apenas quando a condição é avaliada como verdadeira. É possível anexar quantas políticas você quiser a um fluxo condicional. Um fluxo condicional permite criar regras de processamento altamente especializadas para mensagens de solicitação ou resposta que atendam a determinados critérios.

Por exemplo, para criar um fluxo que é executado somente quando o verbo da solicitação é um GET:

<Flows>
  <Flow name="ExecuteForGETs">
  <Condition>request.verb="GET"</Condition>
  </Flow>
</Flows>

Para criar um fluxo para GETs e outro para POSTs:

<Flows>
  <Flow name="ExecuteForGETs">
  <Condition>request.verb="GET"</Condition>
  </Flow>
  <Flow name="ExecuteForPOSTs">
  <Condition>request.verb="POST"</Condition>
  </Flow>
</Flows>

Como mostrado no exemplo abaixo, você pode aplicar a condição à própria etapa da política. A condição a seguir faz com que a política VerifyApiKey seja aplicada somente se uma mensagem de solicitação for um POST.

<PreFlow name="PreFlow">
    <Request>
        <Step>
            <Condition>request.verb equals "POST"</Condition>
            <Name>VerifyApiKey</Name>
        </Step>
    </Request>
</PreFlow>

Assim que você tiver definido esses fluxos condicionais, poderá anexar políticas a eles, permitindo que um proxy de API aplique um conjunto de políticas para solicitações GET e outro conjunto de políticas para solicitações POST.

Para informações de referência abrangentes, consulte os seguintes recursos:

Exemplo 1

O exemplo a seguir mostra um único fluxo condicional chamado Convert-for-devices, configurado no fluxo de resposta de ProxyEndpoint. Adicione a condição como um elemento à entidade a que a condição se aplica. Neste exemplo, a condição é um componente do fluxo. Portanto, o fluxo será executado sempre que a instrução for avaliada como verdadeira.

<Flows>
  <Flow name="Convert-for-devices">
  <Condition>(request.header.User-Agent = "Mozilla")</Condition>
    <Response>
      <Step><Name>ConvertToJSON</Name></Step>
    </Response>
  </Flow>
</Flows>

Para cada solicitação recebida de um aplicativo, o Edge armazena os valores de todos os cabeçalhos HTTP presentes como variáveis. Se a solicitação contiver um cabeçalho HTTP chamado User-Agent, esse cabeçalho e seu valor serão armazenados como uma variável chamada request.header.User-Agent.

Com a configuração de ProxyEndpoint acima, o Edge verifica o valor da variável request.header.User-Agent para ver se a condição é verdadeira.

Se a condição for avaliada como verdadeira, ou seja, o valor da variável request.header.User-Agent for igual a Mozilla, o fluxo condicional será executado e a política XMLtoJSON chamada ConvertToJSON será aplicada. Caso contrário, o fluxo não será executado, e a resposta XML será retornada não modificada (no formato XML) para o app solicitante.

Exemplo 2

Vamos usar um exemplo específico em que você precisa transformar a mensagem de resposta em XML para JSON, mas apenas em dispositivos móveis. Primeiro, crie a política que converterá a resposta formatada em XML da API Weather em JSON:

<XMLToJSON name="ConvertToJSON">
  <Options>
  </Options>
  <OutputVariable>response</OutputVariable>
  <Source>response</Source>
</XMLToJSON>

A configuração da política acima instrui o proxy da API a receber a mensagem da resposta, executar uma conversão de XML para JSON com as configurações padrão e, em seguida, gravar o resultado na nova mensagem de resposta. Se você estiver convertendo uma mensagem de request de XML em JSON, basta definir ambos os valores como request.

Como você quer converter respostas de XML em JSON, é necessário configurar um fluxo de resposta condicional para realizar a conversão. Por exemplo, para converter todas as respostas de XML para JSON antes de serem retornadas para o app cliente, configure o fluxo de resposta ProxyEndpoint a seguir.

<Flows>
  <Flow name="Convert-for-devices">
    <Response>
      <Step><Name>ConvertToJSON</Name></Step>
    </Response>
  </Flow>
</Flows>

Quando você invoca a API usando a solicitação padrão, a resposta é formatada em JSON.

No entanto, sua meta é converter apenas Relatórios meteorológicos em JSON quando o cliente solicitante for um dispositivo móvel. Para ativar esse comportamento dinâmico, você precisa adicionar uma instrução condicional ao fluxo.

Testar o fluxo condicional

Nesta solicitação de amostra, o cabeçalho HTTP User-Agent está definido como Mozilla, fazendo com que a instrução condicional seja avaliada como verdadeira e o fluxo condicional Convert-for-devices seja executado.

$ curl -H "User-Agent:Mozilla" http://{org_name}-test.apigee.net/weather/forecastrss?w=12797282

ou para imprimir onde o Python está disponível:

$ curl -H "User-Agent:Mozilla" http://{org_name}-test.apigee.net/weather/forecastrss?w=12797282 | python -mjson.tool

Exemplo de resposta:

. . .

"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"
          }
      ]
  }

. . .

Uma solicitação enviada sem o cabeçalho User-Agent ou com um valor diferente de Mozilla resultará em uma resposta formatada em XML.

$ curl http://{org_name}-test.apigee.net/weather/forecastrss?w=12797282

A resposta XML não modificada é retornada.

Exemplo de resposta:

<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" />

Correspondência de padrões

Nesta seção, descrevemos como usar a correspondência de padrões com condições em um fluxo da Apigee.

Operadores

Nesta seção, descrevemos como usar os seguintes operadores de correspondência de padrão em instruções condicionais:

Correspondências

Vejamos primeiro o operador condicional "Matches" ou "~". Esses dois operadores são os mesmos. A versão em inglês, "Matches", é considerada uma opção mais legível.

Resumo: o operador "Correspondências" oferece duas possibilidades. Corresponde literalmente à string ou faça uma correspondência curinga com "*". Como você pode esperar, o caractere curinga corresponde a zero ou mais caracteres. Vamos ver como isso funciona.

O XML a seguir mostra uma condição "Step". Ele executa a política SomePolicy quando a condição é avaliada como verdadeira. Neste exemplo, testamos a variável proxy.pathsuffix, uma variável integrada no Edge que armazena o sufixo do caminho da solicitação. No entanto, é possível testar o valor de qualquer variável de fluxo que contenha uma string. Nesse caso, se o caminho base da solicitação de entrada for /animals e a solicitação for /animals/cat, o sufixo do caminho será a string literal "/cat".

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix Matches "/cat")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

Pergunta: Qual sufixo do caminho do proxy fará com que SomePolicy seja executada? Só há uma possibilidade.

Chamada de API:

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

A política é executada? Sim, porque o sufixo do caminho do proxy corresponde exatamente a "/cat". Ela não será executada se o sufixo for /bat, /dog, "/" ou qualquer outra coisa.

Agora, considere esta instrução condicional em que usamos o caractere curinga "*":

<Condition>(proxy.pathsuffix Matches "/*at")</Condition>

Chamada de API:

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

A política é executada? Sim, porque o caractere curinga corresponde a qualquer caractere, e "/cat é uma correspondência.

Chamada de API:

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

A política é executada? Sim, porque o caractere curinga corresponde a qualquer caractere, "/bat" é uma correspondência.

Chamada de API:

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

A política é executada? Claro que não. Embora o caractere curinga corresponda a "o", as letras "wl" não são correspondidas.

Agora, vamos mover o caractere curinga ao final do sufixo:

<Condition>(proxy.pathsuffix Matches "/cat*")</Condition>

Chamada de API:

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

A política é executada? Sim, porque o caractere curinga corresponde a zero ou mais dos caracteres.

Chamada de API:

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

A política é executada? Não, "/bat" não é uma correspondência.

Chamada de API:

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

A política é executada? Sim, o caractere curinga corresponde a zero ou mais caracteres, portanto, "123" produz uma correspondência.

Chamada de API:

GET http://artomatic-test.apigee.net/matchtest/cat/bird/mouse

A política é executada? Sim, porque o caractere curinga corresponde a zero ou mais caracteres. Portanto, "/bird/mouse" produz uma correspondência. Observe como uma expressão como essa pode causar problemas, porque ela corresponde a tudo depois dos caracteres literais.

Pergunta: o operador "Correspondências" diferencia maiúsculas de minúsculas?

Sim. Vamos supor que você tenha uma condição como esta:

<Condition>(proxy.pathsuffix Matches "/*At")</Condition>

Chamada de API:

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

A política é executada? Não, o caractere curinga corresponde a qualquer letra (independentemente do uso de maiúsculas), mas o "a" minúsculo não corresponde a "A".

Chamada de API:

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

A política é executada? Sim, o caso corresponde.

Pergunta: como posso fazer o escape de caracteres com o operador "Correspondências"?

Use o caractere de porcentagem "%" para escapar caracteres reservados. Exemplo:

<Condition>(proxy.pathsuffix Matches "/c%*at")</Condition>

Chamada de API:

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

A política é executada? Não, o operador de correspondências está procurando a string literal "c*at".

Chamada de API:

GET http://artomatic-test.apigee.net/matchtest/c*at

Pergunta:a política é executada?

Sim, com este caminho, embora seja um pouco incomum.

JavaRegex

Como você pode ver, o operador "Correspondências" é ótimo para situações simples. Mas é possível usar outro operador, o operador "JavaRegex" ou "~~". Esses dois são o mesmo operador, mas o JavaRegex é considerado mais legível. Ela tem o nome JavaRegex porque permite a correspondência de padrões de expressões regulares, e o Edge segue as mesmas regras das classes do pacote java.util.regex na linguagem Java. O funcionamento do operador JavaRegex é muito diferente do operador correspondente. Por isso, é importante não confundir.

Resumo: o operador "JavaRegex" permite usar a sintaxe de expressão regular em declarações condicionais.

O código a seguir mostra uma condição "Step". Ela executará a política SomePolicy se a condição for avaliada como verdadeira. Neste exemplo, testamos a variável proxy.pathsuffix, uma variável incorporada no Edge que armazena o sufixo do caminho da solicitação. Se o caminho base da solicitação de entrada for /animals e a solicitação for /animals/cat, o sufixo do caminho será a string literal "/cat".

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix JavaRegex "/cat")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

Pergunta: Qual sufixo do caminho do proxy fará com que SomePolicy seja executada? Assim como acontece com o operador "Correspondências", há apenas uma possibilidade nesse caso.

Chamada de API:

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

A política é executada? Sim, porque o sufixo do caminho do proxy corresponde exatamente a "/cat". Ela não será executada se o sufixo for /bat ou /dog ou qualquer outra coisa.

Agora, vamos criar uma expressão regular usando o quantificador "*". Esse quantificador corresponde a zero ou mais do caractere anterior.

<Condition>(proxy.pathsuffix JavaRegex "/c*t")</Condition>

Chamada de API:

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

A política é executada? Não! O quantificador "*" corresponde a zero ou mais do caractere anterior, que é um "c".

Chamada de API:

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

A política é executada? Sim, porque o caractere curinga corresponde a zero ou mais do caractere anterior.

Em seguida, usamos o quantificador "?", que corresponde ao caractere anterior uma vez ou não está.

<Condition>(proxy.pathsuffix JavaRegex "/ca?t")</Condition>

Chamada de API:

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

A política é executada? Sim. O quantificador "?" corresponde a zero ou uma ocorrência do caractere anterior, que é um "a".

Chamada de API:

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

A política é executada? Sim. O quantificador "?" corresponde a um ou a nenhum dos caracteres anteriores. Nesse caso, não há nenhum caractere "um", então a condição é avaliada como verdadeira.

Chamada de API:

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

A política é executada? Não. O quantificador "?" corresponde a um dos caracteres anteriores, que é um "a".

Em seguida, usamos o estilo "[abc]" ou "agrupamento" da expressão regex. Ele corresponde aos caracteres "a", "b" ou "c".

<Condition>(proxy.pathsuffix JavaRegex "/[cbr]at")</Condition>

Chamada de API:

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

A política é executada? Sim. Estamos usando expressões regulares, e a expressão "[cbr]" corresponde a "c", "b" OU "r". Estas chamadas também são correspondentes:

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

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

No entanto, esta não é uma correspondência:

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

Pergunta: o operador JavaRegex diferencia maiúsculas de minúsculas?

Sim. Vamos supor que você tenha uma condição como esta:

<Condition>(proxy.pathsuffix JavaRegex "/ca?t")</Condition>

Chamada de API:

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

A política é executada? Sim, a regex corresponde a zero ou um dos caracteres anteriores, que é "a".

Chamada de API:

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

Pergunta: a política é executada?

Não, porque a letra "A" não corresponde a "a" em letras minúsculas.

MatchesPath

O operador MatchesPath também pode ser especificado assim: ~/". Ele é um pouco parecido com os operadores Matches (~) e JavaRegex (~~). Mas MatchesPath é totalmente diferente.

Lembre-se de que esse operador analisa um caminho como uma série de partes. Portanto, se o caminho for: /animals/cats/wild, você poderá pensar no caminho como composto pelas partes "/animals", "/cats" e "/wild".

Com o operador MatchesPath, é possível usar duas notações curinga: um asterisco (*) e um asterisco duplo (**). O único asterisco corresponde a um elemento de caminho. O asterisco duplo corresponde a um ou vários elementos de caminho.

Vejamos um exemplo. Neste exemplo, testamos a variável proxy.pathsuffix, uma variável integrada no Edge que armazena o sufixo do caminho da solicitação. No entanto, é possível testar o valor de qualquer variável de fluxo que contenha uma string.

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix MatchesPath "/animals/*")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

Pergunta: Qual sufixo do caminho do proxy fará com que SomePolicy seja executada?

Chamada de API:

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

Pergunta: a política é executada?

Não, porque a condição requer outro elemento de caminho após "/animals", conforme especificado por "/*".

Chamada de API:

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

A política é executada? Sim, ele tem outro elemento de caminho (a parte depois de "/animals/"), mas ele está vazio.

Chamada de API:

GET http://artomatic-test.apigee.net/matchtest/animals/cats

A política é executada? Sim, porque o caminho claramente tem um elemento ("/cats") que vem depois de "/animals".

Chamada de API:

GET http://artomatic-test.apigee.net/matchtest/animals/cats/wild

Pergunta: a política é executada?

Não, porque o único asterisco corresponde apenas a um elemento de caminho, e essa API tem mais de um elemento depois de "/animals".

Agora, vamos usar o asterisco duplo:

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix MatchesPath "/animals/**")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

Pergunta: Qual sufixo do caminho do proxy fará com que SomePolicy seja executada?

Chamada de API:

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

A política é executada? Não, porque a condição exige pelo menos um elemento de caminho a seguir especificado por "/**".

Chamada de API:

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

A política é executada?

Sim, ele tem outro elemento de caminho (a parte depois de "/animals/"), mas ele está vazio.

Chamada de API:

GET http://artomatic-test.apigee.net/matchtest/animals/cats

A política é executada?

Sim, porque o caminho tem pelo menos um elemento que vem depois de "/animals"

Chamada de API:

GET http://artomatic-test.apigee.net/matchtest/animals/cats/wild

A política é executada?

Sim, porque o caminho tem mais de um elemento que vem depois de "/animals"

Misturar asteriscos

É possível usar combinações dos asteriscos simples (*) e duplo (**) para refinar ainda mais sua correspondência de caminho.

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix MatchesPath "/animals/*/wild/**")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

Chamada de API:

Todas essas chamadas de API produzirão uma correspondência:

GET http://artomatic-test.apigee.net/matchtest/animals/cats/wild/

e

GET http://artomatic-test.apigee.net/matchtest/animals/dogs/wild/austrailian

e

GET http://artomatic-test.apigee.net/matchtest/animals/birds/wild/american/finches

Recursos de API

Serviços RESTful são coleções de recursos da API. Um recurso de API é um fragmento de caminho de URI que identifica uma entidade que os desenvolvedores podem acessar chamando sua API. Por exemplo, se o serviço fornece relatórios meteorológicos e previsões do tempo, seu serviço de back-end pode definir dois recursos da API:

  • http://mygreatweatherforecast.com/reports
  • http://mygreatweatherforecast.com/forecasts

Quando você criar um proxy de API (como mostrado em Criar seu primeiro proxy de API), é necessário criar pelo menos um URL base de alias mapeado para o serviço de back-end. Exemplo:

URL base de back-end URL de proxy de API novo/equivalente
http://mygreatweatherforecast.com http://{your_org}-{environment}.apigee.net/mygreatweatherforecast

Nesse ponto, é possível fazer chamadas de API para seu back-end usando qualquer URL de base. Mas quando você usa o URL do proxy da API, as coisas começam a ficar interessantes.

Além da análise da API que o Edge começa a coletar quando você usa o proxy de API, os proxies também permitem definir fluxos condicionais que são mapeados para os recursos no back-end. Basicamente, "Se uma chamada GET chega ao recurso /reports, o Edge deve fazer alguma coisa."

A imagem a seguir mostra a diferença de comportamento entre dois URLs que acessam o mesmo back-end. Um é o URL do recurso sem proxy, o outro é um proxy da API Edge com um fluxo condicional para o mesmo recurso de back-end. Descreveremos os fluxos condicionais em mais detalhes abaixo.

Como os proxies de API são mapeados para recursos de back-end específicos

Com um URL de proxy da API mapeado para o URL base do serviço de back-end (ao criar o proxy), é possível adicionar fluxos condicionais a recursos específicos, como os recursos /reports e /forecasts. mencionado anteriormente.

Digamos que você queira que o Edge "faça algo" quando as chamadas chegarem aos recursos /reports ou /forecasts. Neste ponto, você não está informando ao Edge o que fazer, apenas que ele deve detectar as chamadas para esses recursos. Faça isso com condições. No proxy da API Edge, é possível criar fluxos condicionais para /reports e /forecasts. Para fins conceituais, o seguinte XML de proxy da API mostra como essas condições podem aparecer.

<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>

Essas condições dizem: "Quando uma solicitação GET chega com /reports e /forecasts no URL, o Edge faz o que você (o desenvolvedor da API) pedir, usando as políticas que você anexar a esses fluxos.

Este é um exemplo de como dizer ao Edge o que fazer quando uma condição for atendida. No XML do proxy de API a seguir, quando uma solicitação GET é enviada para https://yourorg-test.apigee.net/mygreatweatherforecast/reports, o Edge executa a política "XML-to-JSON-1" na resposta.

<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>

Além desses fluxos condicionais opcionais, cada proxy de API também tem dois fluxos padrão: um <PreFlow> executado antes dos fluxos condicionais e um <PostFlow> executado depois dos fluxos condicionais. Eles são úteis para executar políticas quando qualquer chamada é feita em um proxy de API. Por exemplo, se você quiser verificar a chave de API de um app em todas as chamadas, independentemente do recurso de back-end que está sendo acessado, poderá colocar uma política "Verificar chave de API" em <PreFlow>. Para mais informações sobre fluxos, consulte Como configurar fluxos.

Criar fluxos condicionais para recursos de back-end

A definição de fluxos condicionais para recursos de back-end em um proxy de API é completamente opcional. No entanto, esses fluxos condicionais permitem aplicar o gerenciamento e o monitoramento refinados.

Você poderá:

  • aplicar o gerenciamento de modo que reflita a semântica do modelo da API;
  • Aplicar políticas e comportamento scriptado a caminhos de recursos individuais (URIs)
  • Coletar métricas refinadas para os serviços do Google Analytics

Por exemplo, imagine que é necessário aplicar diferentes tipos de lógica aos recursos /developers aos recursos /apps.

Para fazer isso, adicione dois fluxos condicionais ao proxy da API: /developers e /apps.

Na visualização "Desenvolvimento" do painel de navegação do editor de proxy da API, clique no ícone + ao lado dos padrões no Endpoints de proxy.

Na janela "New Conditional Flow", insira as seguintes configurações principais:

  • Nome do fluxo: desenvolvedores
  • Tipo de condição: caminho
  • Caminho: /developers

A condição será acionada e as políticas serão executadas se uma chamada for enviada ao proxy com /developers no final do URI.

Agora adicione um fluxo condicional para /apps e suponha que você queira que a condição seja acionada tanto no URI quanto no verbo POST em uma solicitação. A configuração envolve a configuração do seguinte:

  • Nome do fluxo: apps
  • Condition Type: Path e Verb
  • Caminho: /apps
  • Verb: POST

A condição será acionada (e as políticas serão executadas) se uma chamada for enviada ao proxy com /apps no final do URI e um verbo POST.

No painel do Navegador, você verá novos fluxos para Apps e Desenvolvedores.

Selecione um dos fluxos para ver a configuração de fluxo condicional na visualização de código do editor de proxy da 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>

Como você pode ver, os recursos da API são simplesmente fluxos condicionais que avaliam o caminho do URI da solicitação de entrada. A variável proxy.pathsuffix identifica o URI da solicitação que segue o BasePath configurado na configuração do ProxyEndpoint.

Cada recurso de API definido é implementado por um fluxo condicional no proxy da API. Consulte Como configurar fluxos.

Depois de implantar o proxy da API no ambiente de teste, a seguinte solicitação:

http://{org_name}-test.apigee.net/{proxy_path}/apps

fará com que a condição seja avaliada como verdadeira e que esse fluxo, juntamente com todas as políticas associadas, será executado.

O exemplo de condição a seguir usa uma expressão regular Java para reconhecer chamadas feitas para o recurso /apps com ou sem uma barra à direita (/apps ou /apps/**):

<Condition>(proxy.pathsuffix JavaRegex "/apps(/?)") and (request.verb = "POST")</Condition>

Para saber mais sobre esse tipo de condição, consulte Como fazer a correspondência independentemente ... na Comunidade Apigee.

Como modelar URIs hierárquicos

Em alguns casos, você terá recursos hierárquicos da API. Por exemplo, a API dos serviços para desenvolvedores fornece um método para listar todos os apps que pertencem a um desenvolvedor. O caminho do URI é:

/developers/{developer_email}/apps

Você pode ter recursos em que um código exclusivo é gerado para cada entidade em uma coleção, que às vezes é anotada da seguinte maneira:

/genus/:id/species

Esse caminho se aplica igualmente aos dois URIs a seguir:

/genus/18904/species
/genus/17908/species

Para representar essa estrutura em um recurso de API, use caracteres curinga. Exemplo:

/developers/*/apps
/developers/*example.com/apps
/genus/*/species

resolverá esses URIs hierárquicos conforme apropriado os recursos da API.

Em alguns casos, especialmente para APIs profundamente hierárquicas, basta resolver tudo que está abaixo de um determinado fragmento de URI. Para isso, use um caractere curinga de asterisco duplo na definição do recurso. Por exemplo, se você definir o seguinte recurso de API:
/developers/**

Esse recurso de API resolverá os seguintes caminhos de URI:

/developers/{developer_email}/apps
/developers/{developer_email}/keys
/developers/{developer_email}/apps/{app_id}/keys

Veja como ficaria a condição do fluxo condicional na definição do proxy da API:

<Condition>(proxy.pathsuffix MatchesPath "/developers/**") and (request.verb = "POST")</Condition>

Mais exemplos

Condição anexada a 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>

Condição anexada a uma política

<Step>
<!--the policy MaintenancePolicy only executes if the response status code is exactly 503-->
  <Condition>response.status.code = 503</Condition>
  <Name>MaintenancePolicy</Name>
</Step>

Fluxo condicional

<!-- 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>

Operadores de amostra em condições

Veja alguns exemplos de operadores usados para criar condições:

  • 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

Um exemplo prático: ignore "/" no final de um caminho

Os desenvolvedores de borda geralmente querem processar os dois sufixos de caminho: "/cat" e "/cat/". Isso ocorre porque alguns usuários ou clientes podem chamar sua API com a barra extra no final do caminho, e você precisa lidar com isso nas instruções condicionais. Esse caso de uso exato foi discutido na comunidade da Apigee.

Se preferir, você pode fazer isso sem usar o Regex da seguinte maneira:

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>((proxy.pathsuffix = "/cat") OR (proxy.pathsuffix = "/cat/")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

Essa é uma boa opção. É claro e legível.

No entanto, você pode fazer o mesmo com Regex. Os parênteses são usados para agrupar a parte do regex da instrução, mas eles não são necessários.

<Condition>(proxy.pathsuffix JavaRegex "/cat(/?)"</Condition>

Chamadas de API:

GET http://artomatic-test.apigee.net/matchtest/cat
or

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

A política é executada? Sim. Observe que, em uma expressão regular, o caractere "?" significa que: corresponde a zero ou um dos caracteres anteriores. Portanto, "/cat" e "/cat/" são correspondentes.

Chamada de API:

GET http://artomatic-test.apigee.net/matchtest/cat/spotted

A política é executada? Não. A expressão regular corresponde a zero ou apenas uma ocorrência do caractere anterior, e nada mais é permitido.

Correspondência de strings arbitrárias com o JavaRegex

Em todos os exemplos deste tópico, mostramos como corresponder a uma das variáveis de fluxo integradas: proxy.pathsuffix. É bom saber que você pode fazer a correspondência de padrões em qualquer string arbitrária ou variável de fluxo, independentemente de ser uma variável de fluxo integrada, como proxy.pathsuffix.

Por exemplo, se você tiver uma condição que testa uma string arbitrária, talvez uma string retornada em um payload de back-end ou uma string retornada de uma pesquisa do servidor de autenticação, use operadores correspondentes para testá-la. Se você usar o JavaRegex, a expressão regular será comparada com toda a string de assunto. Se o assunto for "abc" e a expressão regular for "[a-z]", não há correspondência, porque "[a-z]" corresponde exatamente a um caractere alfa. A expressão "[a-z]+" funciona, assim como "[a-z]*" e "[a-z]{3}.

Vamos ver um exemplo rápido: Suponha que o servidor de autenticação retorne uma lista de papéis como uma string delimitada por vírgulas: "editor, author, guest".

Para testar a presença do papel de editor, essa construção não funcionará, porque "editor" é apenas parte da string inteira.

<Condition>returned_roles ~~ "editor"</Condition>

No entanto, essa construção funcionará:

<Condition>returned_roles ~~ ".*\beditor\b.*")</Condition>

Ela funciona porque leva em consideração quebras de palavras e quaisquer outras partes da string com o prefixo .*.

Neste exemplo, você também pode testar "editor" com o operador "Correspondências":

<Condition>returned_roles ~~ "*editor*")</Condition>

No entanto, nos casos em que é necessário maior precisão, o JavaRegex geralmente é uma escolha melhor.

Como usar aspas duplas nas expressões JavaRegex

A sintaxe Condition exige que uma expressão JavaRegex esteja entre aspas duplas; Portanto, se você tiver uma expressão regex que inclua aspas duplas, precisará de uma maneira alternativa para correspondê-las. A resposta é Unicode. Por exemplo, digamos que você transmita um cabeçalho com aspas duplas, como no exemplo a seguir:
 -H 'content-type:multipart/related; type="application/xop+xml"'
Se você tentar fazer a correspondência desse cabeçalho em uma condição Regex, vai receber um erro de condição inválida porque a expressão inclui as aspas duplas:
request.header.Content-Type ~~ "(multipart\/related)(; *type="application\/xop\+xml\")"
A solução é substituir as aspas duplas baseadas em ASCII pelo equivalente em Unicode, \u0022. Por exemplo, a expressão a seguir é válida e produz o resultado esperado:
request.header.Content-Type ~~ "(multipart\/related)(; *type=\u0022application\/xop\+xml\u0022)"