Esta página aplica-se ao Apigee e ao Apigee Hybrid.
Veja a documentação do
Apigee Edge.
As declarações condicionais são uma estrutura de controlo comum em todas as linguagens de programação. Tal como uma linguagem de programação, a configuração do proxy de API suporta declarações condicionais para fluxos, políticas, passos e regras de encaminhamento. Ao definir declarações condicionais, define o comportamento dinâmico para a sua API. Este comportamento dinâmico permite-lhe realizar ações como converter XML em JSON apenas para dispositivos móveis ou encaminhar para um URL de back-end com base no tipo de conteúdo ou no verbo HTTP da mensagem de pedido.
Este tópico mostra-lhe como usar condições para aplicar dinamicamente funcionalidades de gestão de APIs em tempo de execução, sem escrever código.
Configure declarações condicionais
O comportamento condicional é implementado em proxies de API através de uma combinação de condições e variáveis. Uma declaração condicional é criada através de um elemento Condition. O seguinte é uma condição vazia:
<Condition></Condition>
Para criar uma declaração condicional, adicione um operador condicional e uma variável com a seguinte sintaxe:
<Condition>VARIABLE_NAME OPERATOR "VALUE"</Condition>
Por exemplo:
<Condition>request.verb = "GET"</Condition>
Os operadores condicionais suportados incluem =
(igual a), !=
(diferente de) e >
(superior a). Para facilitar a leitura, também pode escrever as condições como texto: equals
, notequals
, greaterthan
.
Quando trabalha com caminhos de URI, pode usar ~/
ou MatchesPath
. Também pode fazer a correspondência de expressões regulares JavaRegex com o operador ~~
.
As condições são usadas para definir fluxos condicionais do proxy de API para recursos de API de back-end, descritos em Crie fluxos condicionais para recursos de API de back-end. Para ver uma lista completa de condições, consulte a referência de condições.
Variáveis
As condições fazem o seu trabalho avaliando os valores das variáveis. Uma variável é uma propriedade de uma transação HTTP executada por um proxy de API ou uma propriedade da própria configuração de um proxy de API. Sempre que um proxy de API recebe um pedido de uma app, o Apigee preenche uma longa lista de variáveis associadas a aspetos como a hora do sistema, as informações de rede da app, os cabeçalhos HTTP nas mensagens, a configuração do proxy de API, as execuções de políticas, etc. Isto cria um contexto rico que pode usar para configurar declarações condicionais.
As variáveis usam sempre uma notação com pontos. Por exemplo, os cabeçalhos HTTP na mensagem de pedido estão disponíveis como variáveis denominadas request.header.HEADER_NAME
. Assim, para avaliar o
Content-type header
, pode usar a variável request.header.Content-type
. Por exemplo, request.header.Content-type = "application/json"
indica que o tipo de conteúdo do pedido deve ser JSON.
Imagine que precisa de criar uma declaração condicional que faça com que uma política seja aplicada apenas quando uma mensagem de pedido for um GET
. Para criar uma condição que avalie o verbo HTTP de um pedido, crie a declaração condicional abaixo. A variável nesta condição é
request.verb
. O valor da variável é GET
. O operador é
=
.
<Condition>request.verb = "GET"</Condition>
Também pode usar:
<Condition>request.verb equals "GET"</Condition>
O Apigee usa essa declaração para avaliar as condições. O exemplo acima é avaliado como verdadeiro se o verbo HTTP associado ao pedido for GET
. Se o verbo HTTP associado ao pedido for
POST
, a declaração é avaliada como falsa.
Para ativar o comportamento dinâmico, pode anexar condições a fluxos, passos e regras de encaminhamento.
Quando anexa uma condição a um fluxo, cria um fluxo condicional. Os fluxos condicionais só são executados quando a condição é avaliada como verdadeira. Pode anexar quantas políticas quiser a um fluxo condicional. Um fluxo condicional permite-lhe criar regras de processamento altamente especializadas para mensagens de pedido ou resposta que cumprem determinados critérios.
Por exemplo, para criar um fluxo que é executado apenas quando o verbo de pedido é GET
:
<Flows> <Flow name="ExecuteForGETs"> <Condition>request.verb="GET"</Condition> </Flow> </Flows>
Para criar um Flow para pedidos GET
e outro para pedidos POST
:
<Flows> <Flow name="ExecuteForGETs"> <Condition>request.verb="GET"</Condition> </Flow> <Flow name="ExecuteForPOSTs"> <Condition>request.verb="POST"</Condition> </Flow> </Flows>
Conforme mostrado no exemplo abaixo, pode aplicar a condição ao próprio passo da política. A seguinte condição faz com que a política VerifyAPIKey seja aplicada apenas se uma mensagem de pedido 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, pode anexar-lhes políticas, o que permite a um proxy de API aplicar um conjunto de políticas a pedidos GET
e outro conjunto de políticas a pedidos POST
.
Para obter informações de referência abrangentes, consulte os seguintes recursos:
Exemplo 1
O exemplo seguinte mostra um único fluxo condicional denominado Convert-for-devices
,
configurado no fluxo de resposta do ProxyEndpoint. Adicione a condição como um elemento à entidade à qual a condição se aplica. Neste exemplo, a condição é um componente do fluxo.
Por conseguinte, o fluxo é executado sempre que a declaraçã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 pedido recebido de uma app, o Apigee armazena os valores de todos os cabeçalhos HTTP
presentes como
variáveis. Se o pedido contiver um cabeçalho HTTP denominado User-Agent
, esse cabeçalho e o respetivo valor são armazenados como uma variável denominada request.header.User-Agent
.
Tendo em conta a configuração do ProxyEndpoint acima, o 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 como true
, ou seja, o valor da variável
request.header.User-Agent
for igual a Mozilla
, o fluxo condicional
é executado e a política XMLtoJSON denominada ConvertToJSON
é aplicada. Caso contrário, o Flow
não é executado e a resposta XML é devolvida sem modificações (no formato XML) à app que fez o pedido.
Exemplo 2
Vamos usar um exemplo específico em que precisa de transformar mensagens de resposta de XML para JSON, mas apenas para dispositivos móveis. Primeiro, crie a política que vai 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 indica ao proxy da API que deve receber a mensagem de resposta, fazer uma conversão de XML para JSON com as definições predefinidas e, em seguida, escrever o resultado na nova mensagem de resposta. (Se estiver a converter uma mensagem request de XML para JSON, basta definir ambos os valores como request
.)
Uma vez que quer converter respostas de XML para JSON, tem de configurar um fluxo de respostas condicional para fazer a conversão. Por exemplo, para converter todas as respostas de XML para JSON antes de serem devolvidas à app cliente, configure o seguinte fluxo de resposta ProxyEndpoint.
<Flows> <Flow name="Convert-for-devices"> <Response> <Step><Name>ConvertToJSON</Name></Step> </Response> </Flow> </Flows>
Quando invoca a API através do pedido padrão, a resposta é formatada em JSON.
No entanto, o seu objetivo é apenas converter os relatórios meteorológicos em JSON quando o cliente que faz o pedido é um dispositivo móvel. Para ativar este comportamento dinâmico, tem de adicionar uma declaração condicional ao fluxo.
Teste o fluxo condicional
Neste pedido de exemplo, o cabeçalho HTTP User-Agent
está definido como
Mozilla
, o que faz com que a declaraçã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 ver com estilos de formatação 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" } ] } . . .
Um pedido enviado sem o cabeçalho User-Agent
ou com um valor diferente de
Mozilla
resulta numa resposta formatada em XML.
$ curl http://example.com/weather/forecastrss?w=12797282
A resposta XML não modificada é devolvida.
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
Esta secção descreve como usar a correspondência de padrões com condições num fluxo do Apigee.
Operadores
Esta secção descreve como usar os seguintes operadores de correspondência de padrões em declarações condicionais:
- Operador
Matches
: correspondência de padrões simples - Operador JavaRegex: controlo mais preciso sobre a correspondência
- Operador
MatchesPath
: correspondência de fragmentos de caminho
Correspondências
Vamos analisar primeiro o operador condicional Matches
ou ~
. Estes dois operadores são iguais. A versão em inglês, Matches
, é considerada uma opção mais legível.
Resumo: o operador Matches
oferece-lhe duas possibilidades. Corresponde literalmente à string ou faz uma correspondência de caráter universal com *
. Como seria de esperar, o caráter universal corresponde a zero ou mais carateres. Vejamos como funciona.
O XML seguinte mostra uma condição de passo. Executa a política SomePolicy quando a condição
é avaliada como verdadeira. Neste exemplo, testamos a variável proxy.pathsuffix
, uma variável incorporada no Apigee que armazena o sufixo do caminho do pedido. No entanto, pode testar o valor de qualquer variável de fluxo que contenha uma string. Assim, neste caso, se o caminho base do pedido recebido for /animals
e o pedido for /animals/cat
, o sufixo do caminho é a string literal /cat
.
<PreFlow name="PreFlow"> <Request> <Step> <Condition>(proxy.pathsuffix Matches "/cat")</Condition> <Name>SomePolicy</Name> </Step> </Request> <Response/> </PreFlow>
Pergunta: que sufixo do caminho do proxy faz com que SomePolicy seja executada? Só existe uma possibilidade.
Chamada API:
GET http://example.com/matchtest/cat
A política é executada? Sim, porque o sufixo do caminho do proxy corresponde exatamente a /cat
. Não é executado se o sufixo for /bat
, /dog
, /
ou qualquer outra coisa.
Agora, considere esta declaração condicional em que usamos o caráter universal
*
:
<Condition>(proxy.pathsuffix Matches "/*at")</Condition>
Chamada API:
GET http://example.com/matchtest/cat
A política é executada? Sim, porque o caráter universal corresponde a qualquer caráter e ""/cat
" é uma correspondência.
Chamada API:
GET http://example.com/matchtest/bat
A política é executada? Sim, porque o caráter universal corresponde a qualquer caráter, "/bat"
é uma correspondência.
Chamada API:
GET http://example.com/matchtest/owl
A política é executada? Claro que não. Embora o caráter universal corresponda a o
, as letras wl
não correspondem.
Agora, vamos mover o caráter universal para o fim do sufixo:
<Condition>(proxy.pathsuffix Matches "/cat*")</Condition>
Chamada API:
GET http://example.com/matchtest/cat
A política é executada? Sim, porque o caráter universal corresponde a zero ou mais carateres.
Chamada API:
GET http://example.com/matchtest/bat
A política é executada? Não, /bat
não é uma correspondência.
Chamada API:
GET http://example.com/matchtest/cat123
A política é executada? Sim, o caráter universal corresponde a zero ou mais carateres quaisquer, pelo que
123
produz uma correspondência.
Chamada API:
GET http://example.com/matchtest/cat/bird/mouse
A política é executada? Sim, porque o caráter universal corresponde a zero ou mais carateres quaisquer, pelo que
/bird/mouse
produz uma correspondência. Repare como uma expressão como esta pode causar-lhe problemas, porque corresponde a tudo o que se segue aos carateres literais!
Pergunta: o operador Matches
é sensível a maiúsculas e minúsculas?
Sim. Suponhamos que tem uma condição como esta:
<Condition>(proxy.pathsuffix Matches "/*At")</Condition>
Chamada API:
GET http://example.com/matchtest/cat
A política é executada? Não, o caráter universal corresponde a qualquer letra (independentemente de ser maiúscula ou minúscula), mas o a
em minúsculas não corresponde a A
.
Chamada API:
GET http://example.com/matchtest/bAt
A política é executada? Sim, a capa corresponde.
Pergunta: como posso usar carateres de escape com o operador Matches
?
Use o caráter de percentagem %
para aplicar carateres de escape a carateres reservados. Por exemplo:
<Condition>(proxy.pathsuffix Matches "/c%*at")</Condition>
Chamada API:
GET http://example.com/matchtest/cat
A política é executada? Não, o operador Matches
procura a string literal
c*at
.
Chamada API:
GET http://example.com/matchtest/c*at
Pergunta:a política é executada?
Sim, este caminho, embora um pouco invulgar, corresponde.
JavaRegex
Como pode ver, o operador Matches
é excelente para situações simples. No entanto, pode usar outro operador, o JavaRegex ou o operador ~~
. Estes dois são o mesmo operador, exceto que o JavaRegex é considerado mais legível. Chama-se JavaRegex porque permite a correspondência de padrões de expressões regulares e o Apigee segue as mesmas regras que as classes no pacote java.util.regex na linguagem Java. A forma como o operador JavaRegex funciona é muito diferente do operador Matches
, por isso, é importante não confundir os dois!
Resumo: o operador JavaRegex permite-lhe usar a sintaxe de expressões regulares em instruções condicionais.
O código seguinte mostra uma condição de etapa. Executa a política SomePolicy se a condição for avaliada como true
. Neste exemplo, testamos a variável proxy.pathsuffix
, uma variável integrada no Apigee que armazena o sufixo do caminho do pedido. Se o caminho base do pedido recebido for /animals
e o pedido for /animals/cat
, o sufixo do caminho é a string literal /cat
.
<PreFlow name="PreFlow"> <Request> <Step> <Condition>(proxy.pathsuffix JavaRegex "/cat")</Condition> <Name>SomePolicy</Name> </Step> </Request> <Response/> </PreFlow>
Pergunta: que sufixo do caminho do proxy faz com que SomePolicy seja executada? Tal como com o operador Matches
, só existe uma possibilidade neste caso.
Chamada API:
GET http://example.com/matchtest/cat
A política é executada? Sim, porque o sufixo do caminho do proxy corresponde exatamente a /cat
. Não é executado se o sufixo for /bat
, /dog
ou qualquer outra coisa.
Agora, vamos criar uma expressão regular usando o quantificador *
. Este quantificador corresponde a zero ou mais dos carateres anteriores.
<Condition>(proxy.pathsuffix JavaRegex "/c*t")</Condition>
Chamada API:
GET http://example.com/matchtest/cat
A política é executada? Não! O quantificador *
corresponde a zero ou mais do caráter anterior, que é um c
.
Chamada API:
GET http://example.com/matchtest/ccccct
A política é executada? Sim, porque o caráter universal corresponde a zero ou mais carateres anteriores.
Em seguida, usamos o quantificador ?
, que corresponde ao caráter anterior uma vez ou nenhuma.
<Condition>(proxy.pathsuffix JavaRegex "/ca?t")</Condition>
Chamada API:
GET http://example.com/matchtest/cat
A política é executada? Sim. O quantificador ?
corresponde a zero ou uma ocorrência do caráter anterior, que é um a
.
Chamada API:
GET http://example.com/matchtest/ct
A política é executada? Sim. O quantificador ?
corresponde a um ou
nenhum dos carateres anteriores. Neste caso, não existe o caráter a
, pelo que a condição é avaliada como true
.
Chamada API:
GET http://example.com/matchtest/caat
A política é executada? Não. O quantificador ?
corresponde a um dos carateres
anteriores, que é um a
.
Em seguida, usamos o estilo de [abc]
ou agrupamento da expressão regex. Corresponde aos carateres a
, b
ou c
.
<Condition>(proxy.pathsuffix JavaRegex "/[cbr]at")</Condition>
Chamada API:
GET http://example.com/matchtest/cat
A política é executada? Sim. Estamos a usar expressões regulares aqui e a expressão [cbr]
corresponde a um c
, b
OU r
. Estas chamadas também são correspondências:
GET http://example.com/matchtest/bat
GET http://example.com/matchtest/rat
Mas isto não é uma correspondência:
GET http://example.com/matchtest/mat
Pergunta: o operador JavaRegex é sensível a maiúsculas e minúsculas?
Sim. Suponhamos que tem uma condição como esta:
<Condition>(proxy.pathsuffix JavaRegex "/ca?t")</Condition>
Chamada API:
GET http://example.com/matchtest/cat
A política é executada? Sim, a regex corresponde a zero ou um dos carateres anteriores, que é a
.
Chamada API:
GET http://example.com/matchtest/cAt
Pergunta: a política é executada?
Não, porque a letra maiúscula A
não corresponde à letra minúscula a
.
MatchesPath
O operador MatchesPath
também pode ser especificado desta forma ~/
. Parece
um pouco com os operadores
Matches
(~
) e JavaRegex (~~
). Mas
MatchesPath
é completamente diferente.
Lembre-se de que este operador considera um caminho como uma série de partes. Por conseguinte, se o caminho for /animals/cats/wild
, pode considerar que o caminho é composto pelas partes /animals
, /cats
e /wild
.
O operador MatchesPath
permite-lhe usar duas notações de carateres universais: um asterisco único (*) e um asterisco duplo (**
). O asterisco único corresponde a um elemento do caminho. O duplo asterisco corresponde a um ou vários elementos do caminho.
Vejamos um exemplo. Neste exemplo, testamos a variável proxy.pathsuffix
, uma variável incorporada no Apigee que armazena o sufixo do caminho do pedido. No entanto, pode 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: que sufixo do caminho do proxy faz com que SomePolicy seja executada?
Chamada 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 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 está vazio.
Chamada API:
GET http://example.com/matchtest/animals/cats
A política é executada? Sim, porque o caminho tem claramente um elemento (/cats
)
que surge depois de /animals
Chamada API:
GET http://example.com/matchtest/animals/cats/wild
Pergunta: a política é executada?
Não, porque o asterisco único só corresponde a um elemento de caminho e esta API tem mais do que um elemento após /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: que sufixo do caminho do proxy faz com que SomePolicy seja executada?
Chamada API:
GET http://example.com/matchtest/animals
A política é executada? Não, porque a condição requer, pelo menos, um elemento do caminho seguinte especificado por /**
.
Chamada 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 está vazio.
Chamada API:
GET http://example.com/matchtest/animals/cats
A política é executada?
Sim, porque o caminho tem, pelo menos, um elemento que surge depois de
/animals
Chamada API:
GET http://example.com/matchtest/animals/cats/wild
A política é executada?
Sim, porque o caminho tem mais do que um elemento que vem depois de
/animals
Misturar asteriscos
Pode usar combinações do asterisco único (*) e duplo (**) para refinar ainda mais a correspondência de caminhos.
<PreFlow name="PreFlow"> <Request> <Step> <Condition>(proxy.pathsuffix MatchesPath "/animals/*/wild/**")</Condition> <Name>SomePolicy</Name> </Step> </Request> <Response/> </PreFlow>
Chamada API:
Todas estas chamadas API produzem 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 da API
Os serviços RESTful são coleções de recursos da API. Um recurso da API é um fragmento do caminho do URI que identifica alguma entidade à qual os programadores podem aceder chamando a sua API. Por exemplo, se o seu serviço fornecer relatórios meteorológicos e previsões meteorológicas, o serviço de back-end pode definir dois recursos de API:
http://mygreatweatherforecast.com/reports
http://mygreatweatherforecast.com/forecasts
Quando cria um proxy de API (conforme mostrado no artigo Crie o seu primeiro proxy de API), está a criar, no mínimo, um URL base de alias que é mapeado para o seu serviço de back-end. Por exemplo:
URL de base do back-end | URL do proxy de API novo/equivalente |
---|---|
http://mygreatweatherforecast.com |
http://example.com/mygreatweatherforecast |
Neste ponto, pode fazer chamadas API para o seu back-end através de qualquer um dos URLs base. No entanto, quando usa o URL do proxy da API, as coisas começam a ficar interessantes.
Além das estatísticas da API que o Apigee começa a recolher quando usa o proxy de API, os proxies
também lhe permitem definir fluxos condicionais que são mapeados para os recursos no seu back-end. Essencialmente, se
uma chamada for recebida no recurso /reports
, o Apigee deve fazer algo.GET
A imagem seguinte mostra a diferença de comportamento entre dois URLs que, em última análise, acedem ao mesmo back-end. Um é o URL do recurso sem proxy e o outro é um proxy de API do Apigee com um fluxo condicional para o mesmo recurso de back-end. Vamos descrever os fluxos condicionais mais detalhadamente 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 (quando cria o proxy), pode adicionar fluxos condicionais a recursos específicos, como os recursos /reports
e /forecasts
mencionados anteriormente.
Suponhamos que quer que o Apigee faça algo quando as chamadas são recebidas nos recursos /reports
ou /forecasts
. Neste ponto, não está a dizer ao Apigee o que fazer, apenas que deve estar a ouvir chamadas para esses recursos. Pode fazê-lo
com condições. No proxy de API do Apigee, pode criar fluxos condicionais para
/reports
e /forecasts
. Para fins conceptuais, o seguinte XML do proxy da API mostra o aspeto que essas condições podem ter.
<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 indicam que quando chega um pedido GET
com /reports
e
/forecasts
no URL, o Apigee faz o que lhe é indicado (o programador de APIs),
através das políticas que associa a esses fluxos.
Segue-se um exemplo de como indicar ao Apigee o que fazer quando uma condição é cumprida. No XML do proxy da API seguinte, quando um pedido GET
é enviado para https://example.com/mygreatweatherforecast/reports
, o 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 inclui dois fluxos
predefinidos: um <PreFlow>
executado antes dos fluxos condicionais e um
<PostFlow>
executado após os fluxos condicionais. Estas são úteis para executar políticas quando qualquer chamada é feita a um proxy de API. Por exemplo, se quiser
validar a chave da API de uma app com cada chamada, independentemente do recurso de back-end acedido, pode
colocar uma política de validação da chave da API no <PreFlow>
. Para mais informações sobre fluxos, consulte o artigo
Configurar fluxos.
Crie fluxos condicionais para recursos de back-end
A definição de fluxos condicionais para recursos de back-end num proxy de API é totalmente opcional. No entanto, esses fluxos condicionais permitem-lhe aplicar uma gestão e uma monitorização detalhadas.
Vai poder:
- Aplique a gestão de uma forma que reflita a semântica do seu modelo de API
- Aplique políticas e comportamento com scripts a caminhos de recursos individuais (URIs)
- Recolha métricas detalhadas para os serviços do Analytics
Por exemplo, imagine que precisa de aplicar diferentes tipos de lógica ao seu back-end
/developers
para /apps
recursos.
Para o fazer, adicione dois fluxos condicionais no proxy de API: /developers
e
/apps
.
Novo editor de proxy
Para adicionar um fluxo condicional:
- Selecione o separador Desenvolver no editor de proxy.
- Selecione Terminais de proxy > predefinição no painel do lado esquerdo.
- Clique no botão + acima do painel Resposta.
- Na caixa de diálogo Adicionar fluxo condicional, introduza as seguintes configurações:
- Nome do fluxo:
Developers
- Tipo de condição:
Path
- Caminho:
/developers
A condição é acionada (e as políticas são executadas) se for enviada uma chamada ao proxy com
/developers
no final do URI. - Nome do fluxo:
- Agora, adicione um fluxo condicional para
/apps
e suponha que quer que a condição seja acionada no URI e no verboPOST
num pedido. A configuração envolve a definição do seguinte:- Nome do fluxo:
Apps
- Tipo de condição:
Path and Verb
- Caminho:
/apps
- Verbo:
POST
A condição é acionada (e as políticas são executadas) se for enviada uma chamada ao proxy com
/apps
no final do URI e um verboPOST
. - Nome do fluxo:
Os fluxos adicionados são apresentados no painel Resposta:
Editor de proxy clássico
No painel Develop do painel Navigator do editor de proxy de API, clique em
junto a default em Proxy Endpoints.
Na janela Novo fluxo condicional, introduza as seguintes configurações principais:
- Nome do fluxo:
Developers
- Tipo de condição:
Path
- Caminho:
/developers
A condição é acionada (e as políticas são executadas) se for enviada uma chamada ao proxy com /developers
no final do URI.
Agora, adicione um fluxo condicional para /apps
e suponha que quer que a condição seja acionada no URI e no verbo POST
num pedido. A configuração envolve a definição do seguinte:
- Nome do fluxo:
Apps
- Tipo de condição:
Path and Verb
- Caminho:
/apps
- Verbo:
POST
A condição é acionada (e as políticas são executadas) se for enviada uma chamada ao proxy com /apps
no final do URI e um verbo POST
.
No painel Navegador, vai ver novos fluxos para Apps e Programadores.
Selecione um dos fluxos para ver a configuração do fluxo condicional na vista de código do editor do proxy de 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 pode ver, os recursos da API são simplesmente fluxos condicionais que avaliam o caminho do URI do pedido recebido. (A variável proxy.pathsuffix
identifica o URI do pedido que segue
o BasePath configurado na configuração do ProxyEndpoint.)
Cada recurso de API que define é implementado por um fluxo condicional no proxy de API. (Consulte a secção Configurar fluxos.)
Depois de implementar o proxy de API no ambiente de teste, o seguinte pedido:
http://example.com/PROXY_PATH/apps
faz com que a condição seja avaliada como true
e este fluxo, juntamente com quaisquer políticas associadas, seja executado.
A condição de exemplo seguinte usa uma expressão regular Java para reconhecer chamadas feitas ao recurso /apps
com ou sem uma barra invertida final (/apps
ou /apps/**
):
<Condition>(proxy.pathsuffix JavaRegex "/apps(/?)") and (request.verb = "POST")</Condition>
Para saber mais sobre este tipo de condição, consulte o artigo Como fazer a correspondência independentemente de existir um "/" no final... na comunidade do Apigee.
Modelagem de URIs hierárquicos
Em alguns casos, tem recursos de API hierárquicos. Por exemplo, a API Developer apps list oferece um método para listar todas as apps que pertencem a um programador. O caminho do URI é:
/developers/DEVELOPER_EMAIL/apps
Pode ter recursos em que é gerado um ID exclusivo para cada entidade numa coleção, que é, por vezes, anotado da seguinte forma:
/genus/:id/species
Este caminho aplica-se igualmente aos dois URIs seguintes:
/genus/18904/species /genus/17908/species
Para representar esta estrutura num recurso de API, pode usar carateres universais. Por exemplo:
/developers/*/apps /developers/*example.com/apps /genus/*/species
Estes resolvem os URIs hierárquicos como recursos da API de forma adequada.
Em alguns casos, especialmente para APIs profundamente hierárquicas, pode simplesmente querer resolver tudo abaixo de um determinado fragmento de URI. Para o fazer, use um caráter universal de asterisco duplo na definição do recurso. Por exemplo, se definir o seguinte recurso da API:
/developers/**
Esse recurso da API resolve os seguintes caminhos URI:
/developers/DEVELOPER_EMAIL/apps /developers/DEVELOPER_EMAIL/keys /developers/DEVELOPER_EMAIL/apps/APP_ID/keys
Veja o aspeto da condição de fluxo condicional na definição do proxy de API:
<Condition>(proxy.pathsuffix MatchesPath "/developers/**") and (request.verb = "POST")</Condition>
Mais exemplos
Condição associada 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>
Exemplos de operadores em condições
Seguem-se 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: ignorar
/
no final de um caminho
Normalmente, os programadores do Apigee querem processar ambos os sufixos de caminho: /cat
e
/cat/
. Isto deve-se ao facto de alguns utilizadores ou clientes poderem chamar a sua API com a barra
adicional no final do caminho, e tem de conseguir processar isso nas suas declarações
condicionais. Este exemplo de utilização exato foi abordado no artigo
como fazer a correspondência independentemente de existir um "/" no final do URL....
Se preferir, pode fazê-lo sem usar regex da seguinte forma:
<PreFlow name="PreFlow"> <Request> <Step> <Condition>(proxy.pathsuffix = "/cat") OR (proxy.pathsuffix = "/cat/")</Condition> <Name>SomePolicy</Name> </Step> </Request> <Response/> </PreFlow>
Esta é uma boa opção. É clara e legível.
Pode fazer o mesmo com a Regex, mas da seguinte forma. Os parênteses são usados para agrupar a parte regex da declaração, mas não são obrigatórios.
<Condition>(proxy.pathsuffix JavaRegex "/cat(/?)"</Condition>
Chamadas da API:
GET http://example.com/matchtest/cat
ou
GET http://example.com/matchtest/cat
/
A política é executada? Sim. Tenha em atenção que, numa expressão regular, o caráter ?
significa: corresponder a zero ou um dos carateres anteriores. Por conseguinte, /cat
e /cat/
são correspondências.
Chamada 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 caráter anterior e não é permitido mais nada.
Fazer corresponder strings arbitrárias com JavaRegex
Em todos os exemplos neste tópico, mostramos como fazer a correspondência de uma das variáveis de fluxo incorporadas:
proxy.pathsuffix
. É útil saber que pode fazer a correspondência de padrões em qualquer string arbitrária ou variável de fluxo, quer seja ou não uma variável de fluxo incorporada, como proxy.pathsuffix
.
Por exemplo, se tiver uma condição que teste uma string arbitrária, talvez uma string devolvida num payload de back-end ou uma string devolvida a partir de uma pesquisa de servidor de autenticação, pode usar operadores de correspondência para a testar. Se usar JavaRegex
, a expressão regular é comparada com a string de assunto completa. Se o assunto for abc
e a expressão regular for [a-z]
,
não existe uma correspondência, porque [a-z]
corresponde exatamente a um caráter alfabético. A expressão [a-z]+
funciona, tal como [a-z]*
e [a-z]{3}
.
Vejamos um exemplo concreto. Suponhamos que o servidor de autenticação devolve uma lista de funções como uma string delimitada por vírgulas: editor, author, guest
.
Para testar a presença da função de editor, esta construção não funciona, porque editor
faz
apenas parte da string completa.
<Condition>returned_roles ~~ "editor"</Condition>
No entanto, esta construção funciona:
<Condition>(returned_roles ~~ ".*\beditor\b.*")</Condition>
Funciona porque tem em conta as quebras de palavras e quaisquer outras partes da string com o prefixo e o sufixo .*
.
Neste exemplo, também pode testar editor
com o operador Matches
:
<Condition>(returned_roles ~~ "*editor*")</Condition>
No entanto, nos casos em que precisa de mais precisão, o JavaRegex é frequentemente uma escolha melhor.
Evitar aspas duplas em expressões JavaRegex
A sintaxe da condição requer que uma expressão JavaRegex seja incluída entre aspas. Por conseguinte, se tiver uma expressão regex que inclua aspas, precisa de uma forma alternativa de as fazer corresponder. A resposta é Unicode. Por exemplo, suponhamos que transmite um cabeçalho que inclui aspas duplas, como o seguinte:
-H 'content-type:multipart/related; type="application/xop+xml"'
Se tentar fazer corresponder esse cabeçalho numa condição de regex, recebe um erro Invalid Condition
porque a expressão inclui as aspas:
request.header.Content-Type ~~ "(multipart\/related)(; *type="application\/xop\+xml\")"
A solução consiste em substituir as aspas duplas baseadas em ASCII pelo respetivo equivalente Unicode, \u0022
. Por exemplo, a expressão seguinte é válida e produz o resultado esperado:
request.header.Content-Type ~~ "(multipart\/related)(; *type=\u0022application\/xop\+xml\u0022)"