Condições com variáveis de fluxo

Esta página se aplica à Apigee e à Apigee híbrida.

Confira a documentação da Apigee Edge.

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 condições e variáveis. 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 usando a seguinte sintaxe:

<Condition>VARIABLE_NAME OPERATOR "VALUE"</Condition>

Exemplo:

<Condition>request.verb = "GET"</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. Também é possível 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, a Apigee preenche uma longa lista de variáveis associadas a itens como tempo do sistema, informações de rede do aplicativo, cabeçalhos HTTP em mensagens, configuração do proxy da API, execuções de política 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 Content-type header, 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>

Também é possível usar o seguinte:

<Condition>request.verb equals "GET"</Condition>

A Apigee usa uma instrução como essa para avaliar 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 solicitações GET e outro para solicitações POST, faça o seguinte:

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

Depois de definir esses fluxos condicionais, é possível anexar políticas a eles, permitindo que um proxy da API aplique um conjunto de políticas às 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 true.

<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, a Apigee 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 ProxyEndpoint acima, a Apigee verifica o valor da variável request.header.User-Agent para ver se a condição é avaliada como verdadeira.

Se a condição for avaliada para true, ou seja, o valor da variável request.header.User-Agent é igual aMozilla, o fluxo condicional será executado, e oPolítica XMLtoJSON chamadoConvertToJSON é 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://example.com/weather/forecastrss?w=12797282

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

curl -H "User-Agent:Mozilla" http://example.com/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://example.com/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 Matches oferece duas possibilidades. Corresponda literalmente à string ou faça uma correspondência curinga com *. Como o esperado, 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 na Apigee 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://example.com/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://example.com/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://example.com/matchtest/bat

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

Chamada de API:

GET http://example.com/matchtest/owl

A política é executada? Certamente 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://example.com/matchtest/cat

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

Chamada de API:

GET http://example.com/matchtest/bat

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

Chamada de API:

GET http://example.com/matchtest/cat123

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

Chamada de API:

GET http://example.com/matchtest/cat/bird/mouse

A política é executada? Sim, porque o caractere curinga corresponde a zero ou mais dos caracteres, de modo que /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 Matches 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://example.com/matchtest/cat

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

Chamada de API:

GET http://example.com/matchtest/bAt

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

Pergunta: como posso fazer o escape de caracteres com o operador Matches

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

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

Chamada de API:

GET http://example.com/matchtest/cat

A política é executada? Não, o operador Matches está procurando a string literal c*at.

Chamada de API:

GET http://example.com/matchtest/c*at

Pergunta:a política é executada?

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

JavaRegex

O operador Matches é ótimo para situações simples. Mas é possível usar outro operador, como JavaRegex ou ~~. Esses dois são o mesmo operador, mas o JavaRegex é considerado mais legível. Ela é chamada de JavaRegex porque permite a correspondência de padrões de expressão regular, e a Apigee segue as mesmas regras que as classes do pacote java.util.regex na linguagem Java. O funcionamento do operador JavaRegex é muito diferente do operador Matches. Portanto, é importante não confundir os dois.

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". Ele executará a política SomePolicy se a condição for avaliada como true. Neste exemplo, testamos a variável proxy.pathsuffix, uma variável integrada na Apigee 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 com o operador Matches, há apenas uma possibilidade nesse caso.

Chamada de API:

GET http://example.com/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 dos caracteres anteriores.

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

Chamada de API:

GET http://example.com/matchtest/cat

A política é executada? Não. O quantificador * corresponde ao caractere anterior, que é umc.

Chamada de API:

GET http://example.com/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 nenhum.

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

Chamada de API:

GET http://example.com/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://example.com/matchtest/ct

A política é executada? Sim. O quantificador ? corresponde a um ou nenhum do caractere anterior. Nesse caso, não há caractere a. Portanto, a condição é avaliada como true.

Chamada de API:

GET http://example.com/matchtest/caat

A política é executada? Não. O quantificador ? corresponde a um do caractere anterior, que é um a.

Em seguida, usaremos 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://example.com/matchtest/cat

A política é executada? Sim. Aqui, 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://example.com/matchtest/bat

GET http://example.com/matchtest/rat

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

GET http://example.com/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://example.com/matchtest/cat

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

Chamada de API:

GET http://example.com/matchtest/cAt

Pergunta: a política é executada?

Não, porque o A maiúsculo não corresponde ao a minúsculo.

MatchesPath

O operador MatchesPath também pode ser especificado assim: ~/. Ele é similar aos operadores Matches (~) e JavaRegex (~~). No entanto, 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 parte das 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 na Apigee 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://example.com/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://example.com/matchtest/animals/

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

Chamada de API:

GET http://example.com/matchtest/animals/cats

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

Chamada de API:

GET http://example.com/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://example.com/matchtest/animals

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

Chamada de API:

GET http://example.com/matchtest/animals/

A política é executada?

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

Chamada de API:

GET http://example.com/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://example.com/matchtest/animals/cats/wild

A política é executada?

Sim, porque o caminho tem mais de um elemento que vem após /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://example.com/matchtest/animals/cats/wild/

e

GET http://example.com/matchtest/animals/dogs/wild/austrailian

e

GET http://example.com/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://example.com/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 a Apigee começa a coletar quando você usa o proxy da API, os proxies também permitem definir fluxos condicionais que mapeiam os recursos no back-end. Essencialmente, se uma chamada GET chega ao recurso /reports, a Apigee precisa fazer algo.

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 de API da Apigee com um fluxo condicional para o mesmo recurso de back-end. Descreveremos os fluxos condicionais em mais detalhes abaixo.

Para o URL do proxy da API Apigee com um fluxo condicional, a resposta converte XML em JSON
    e coleta dados de análise.

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 a Apigee faça algo quando as chamadas chegam aos recursos /reports ou /forecasts. Você não informa ao Apigee o que fazer, apenas que ele precisa detectar chamadas para esses recursos. Faça isso com condições. No proxy da API Apigee, é 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 que Quando uma solicitação GET vem com /reports e /forecasts no URL, a Apigee faz tudo o que você (o desenvolvedor da API) informa, por meio das políticas anexadas. para esses fluxos.

Veja um exemplo de dizer ao Apigee o que fazer quando uma condição é atendida. No XML de proxy de API a seguir, quando uma solicitação GET é enviada para https://example.com/mygreatweatherforecast/reports, a Apigee 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 você precisa aplicar tipos diferentes de lógica aos recursos de back-end /developers a /apps.

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

Novo Editor de proxy

Para adicionar um fluxo condicional, faça o seguinte:

  1. Selecione a guia Develop no Proxy Editor.
  2. Selecione Proxy endpoints > default no painel à esquerda.

    default no painel à esquerda." class="l10n-absolute-url-src screenshot" l10n-attrs-original-order="class,width,alt,src" src="https://cloud.google.com/static/apigee/docs/api-platform/fundamentals/images/proxy-endpoints-default.png" width="35%" />

  3. Clique no botão + acima do painel Resposta.

    Botão para adicionar fluxo condicional

  4. Na caixa de diálogo Add consigo Flow, insira as seguintes configurações:
    • Nome do fluxo: Developers
    • Tipo de condição: Path
    • Caminho: /developers

    Caixa de diálogo "Adicionar fluxo condicional".

    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.

  5. 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
    • Tipo de condição: Path and Verb
    • Caminho: /apps
    • Verbo: 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.

Os fluxos adicionados são exibidos no painel Response:

Caixa de diálogo "Adicionar fluxo condicional".

Editor de proxy clássico

No painel Desenvolvimento do editor do proxy de API de Navegador, clique em ao lado de padrão nos Endpoints de proxy.

Quando você segura o ponteiro do mouse sobre o sinal de mais ao lado do padrão, o texto exibido ao passar o cursor é &quot;Adicionar
  novo fluxo&quot;.

Na janela Novo fluxo condicional, insira as seguintes configurações de chave:

  • Nome do fluxo: Developers
  • Tipo de condição: Path
  • Caminho: /developers

No painel &quot;New Conditional Flow&quot;, um fluxo chamado &quot;Developers&quot; é configurado com a
    descrição &quot;Developer app registered with Developer Services&quot;.

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
  • Tipo de condição: Path and Verb
  • Caminho: /apps
  • Verbo: POST

No painel &quot;Novo fluxo condicional&quot;, um fluxo chamado &quot;Apps&quot; é configurado com a
    descrição &quot;Aplicativos do desenvolvedor registrados nos Serviços para desenvolvedores&quot;.

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.

Os novos fluxos para aplicativos e desenvolvedores são mostrados no painel &quot;Navigator&quot; em &quot;Endpoints
    de proxy&quot;.

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://example.com/PROXY_PATH/apps

fará com que a condição seja avaliada como true e que esse fluxo, 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 de haver um "/" antes de ... naComunidade da Apigee.

Como modelar URIs hierárquicos

Em alguns casos, você terá recursos hierárquicos da API. Por exemplo, a API Developer Apps list 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

Eles resolverão os URIs hierárquicos como recursos da API corretamente.

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 da 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 da Apigee costumam querer lidar com os seguintes sufixos de caminho: /cat e /cat/. Isso ocorre porque alguns usuários ou clientes podem chamar a API com uma barra extra no final do caminho. Você precisa ser capaz de lidar com isso nas declarações condicionais. Esse caso de uso exato foi discutido em Como fazer a correspondência independentemente de haver um "/ no URL...

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://example.com/matchtest/cat
or
GET http://example.com/matchtest/cat/

A política é executada? Sim. Em uma expressão regular, o caractere ? significa: corresponder a zero ou a um dos caracteres anteriores. Portanto, /cat e /cat/ são correspondências.

Chamada de API:

GET http://example.com/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. É possível fazer a correspondência de padrões em qualquer string arbitrária ou variável de fluxo, independentemente de ser ou não 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 JavaRegex, a expressão regular será comparada com a string do assunto inteiro. 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 de toda a string.

<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, também é possível testar editor com o operador Matches:

<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ê passe um cabeçalho que inclua aspas duplas, como:

 -H 'content-type:multipart/related; type="application/xop+xml"'

Se você tentar corresponder esse cabeçalho a uma condição regex, verá um erro Invalid Condition porque a expressão inclui aspas duplas:

request.header.Content-Type ~~ "(multipart\/related)(; *type="application\/xop\+xml\")"

A solução é substituir as aspas duplas baseadas em ASCII pelo equivalente 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)"