Questa pagina si applica ad Apigee e Apigee hybrid.
Visualizza la documentazione di Apigee Edge.
Le istruzioni condizionali sono una struttura di controllo comune in tutti i linguaggi di programmazione. Come un linguaggio di programmazione, la configurazione del proxy API supporta le istruzioni condizionali per flussi, criteri, passaggi e regole di routing. Se definisci istruzioni condizionali, definisci un comportamento dinamico per la tua API. Questo comportamento dinamico ti consente di eseguire operazioni come la conversione di XML in JSON solo per i dispositivi mobili o il reindirizzamento a un URL di backend in base al tipo di contenuti o al verbo HTTP del messaggio di richiesta.
Questo argomento mostra come utilizzare le condizioni per applicare dinamicamente le funzionalità di gestione delle API in fase di esecuzione, senza scrivere codice.
Configurare le istruzioni condizionali
Il comportamento condizionale viene implementato nei proxy API utilizzando una combinazione di condizioni e variabili. Un'istruzione condizionale viene creata utilizzando un elemento Condition. La seguente è una condizione vuota:
<Condition></Condition>
Per creare un'istruzione condizionale, aggiungi un operatore condizionale e una variabile utilizzando la seguente sintassi:
<Condition>VARIABLE_NAME OPERATOR "VALUE"</Condition>
Ad esempio:
<Condition>request.verb = "GET"</Condition>
Gli operatori condizionali supportati includono =
(uguale a), !=
(non uguale a)
e >
(maggiore di). Per una maggiore leggibilità, puoi anche scrivere le condizioni come testo: equals
, notequals
, greaterthan
.
Quando lavori con i percorsi URI, puoi utilizzare ~/
o MatchesPath
. Puoi anche trovare corrispondenze con le espressioni regolari JavaRegex utilizzando l'operatore ~~
.
Le condizioni vengono utilizzate per definire i flussi condizionali del proxy API alle risorse API di backend, descritti in Creare flussi condizionali alle risorse API di backend. Per un elenco completo dei condizionali, consulta la sezione Riferimento alle condizioni.
Variabili
Le condizioni svolgono il loro compito valutando i valori delle variabili. Una variabile è una proprietà di una transazione HTTP eseguita da un proxy API o una proprietà della configurazione stessa di un proxy API. Ogni volta che un proxy API riceve una richiesta da un'app, Apigee compila un lungo elenco di variabili associate ad elementi quali l'ora di sistema, le informazioni di rete dell'app, le intestazioni HTTP sui messaggi, la configurazione del proxy API, le esecuzioni dei criteri e così via. Viene creato un contesto completo che puoi utilizzare per configurare le istruzioni condizionali.
Le variabili utilizzano sempre una notazione con puntini. Ad esempio, le intestazioni HTTP nel messaggio di richiesta sono disponibili come variabili chiamate request.header.HEADER_NAME
. Pertanto, per valutare Content-type header
, puoi utilizzare la variabile request.header.Content-type
. Ad esempio, request.header.Content-type = "application/json"
indica che il tipo di contenuti della richiesta deve essere JSON.
Immagina di dover creare un'istruzione condizionale che imponga l'applicazione di una norma solo quando un messaggio di richiesta è un GET
. Per creare una condizione che valuti il verbo HTTP
di una richiesta, crea l'istruzione condizionale riportata di seguito. La variabile in questa condizione è
request.verb
. Il valore della variabile è GET
. L'operatore è
=
.
<Condition>request.verb = "GET"</Condition>
Puoi anche utilizzare:
<Condition>request.verb equals "GET"</Condition>
Apigee utilizza questa istruzione per valutare le condizioni. L'esempio riportato sopra restituisce true se il verbo HTTP associato alla richiesta è GET
. Se il verbo HTTP associato alla richiesta è
POST
, l'istruzione ha il valore false.
Per attivare il comportamento dinamico, puoi associare le condizioni a flussi, passaggi e regole di routing.
Quando colleghi una condizione a un flusso, crei un flusso condizionale. I flussi condizionali vengono eseguiti solo quando la condizione ha valore true. Puoi allegare tutti i criteri che vuoi a un flusso condizionale. Un flusso condizionale ti consente di creare regole di elaborazione altamente specializzate per i messaggi di richiesta o risposta che soddisfano determinati criteri.
Ad esempio, per creare un flusso che venga eseguito solo quando il verbo della richiesta è GET
:
<Flows> <Flow name="ExecuteForGETs"> <Condition>request.verb="GET"</Condition> </Flow> </Flows>
Per creare un flusso per le richieste GET
e un altro per le richieste POST
:
<Flows> <Flow name="ExecuteForGETs"> <Condition>request.verb="GET"</Condition> </Flow> <Flow name="ExecuteForPOSTs"> <Condition>request.verb="POST"</Condition> </Flow> </Flows>
Come mostrato nell'esempio di seguito, puoi applicare la condizione al passaggio del criterio stesso. La
seguente condizione fa sì che il criterio VerifyAPIKey venga applicato solo se un messaggio di richiesta è un
POST
.
<PreFlow name="PreFlow"> <Request> <Step> <Condition>request.verb equals "POST"</Condition> <Name>VerifyApiKey</Name> </Step> </Request> </PreFlow>
Una volta definiti questi flussi condizionali, puoi associarvi i criteri, consentendo a un proxy API di applicare un insieme di criteri per le richieste GET
e un altro insieme di criteri per le richieste POST
.
Per informazioni di riferimento complete, consulta le seguenti risorse:
Esempio 1
L'esempio seguente mostra un singolo flusso condizionale denominato Convert-for-devices
, configurato nel flusso di risposta ProxyEndpoint. Aggiungi la condizione come elemento all'entità a cui si applica. In questo esempio, la condizione è un componente del flusso.
Pertanto, il flusso verrà eseguito ogni volta che l'istruzione restituisce true
.
<Flows> <Flow name="Convert-for-devices"> <Condition>(request.header.User-Agent = "Mozilla")</Condition> <Response> <Step><Name>ConvertToJSON</Name></Step> </Response> </Flow> </Flows>
Per ogni richiesta ricevuta da un'app, Apigee memorizza i valori di tutte le intestazioni HTTP presenti come variabili. Se la richiesta contiene un'intestazione HTTP denominata User-Agent
, questa intestazione e il suo valore vengono memorizzati come una variabile denominata request.header.User-Agent
.
Data la configurazione di ProxyEndpoint riportata sopra, Apigee controlla il valore della variabile request.header.User-Agent
per verificare se la condizione è valutata come true.
Se la condizione ha come risultato true
, ovvero il valore della variabile request.header.User-Agent
è uguale a Mozilla
, il flusso condizionale viene eseguito e il criterio XMLtoJSON denominato ConvertToJSON
viene applicato. In caso contrario, il flusso
non viene eseguito e la risposta XML viene restituita non modificata (in formato XML) all'app richiedente.
Esempio 2
Utilizziamo un esempio specifico in cui devi trasformare il messaggio di risposta da XML in JSON, ma solo per i dispositivi mobili. Innanzitutto, crea il criterio che convertirà la risposta in formato XML dell'API meteo in JSON:
<XMLToJSON name="ConvertToJSON"> <Options> </Options> <OutputVariable>response</OutputVariable> <Source>response</Source> </XMLToJSON>
La configurazione delle norme riportata sopra indica al proxy API di prendere il messaggio di risposta, eseguire una conversione da XML a JSON con le impostazioni predefinite e scrivere il risultato nel nuovo messaggio di risposta. Se stai convertendo un messaggio di richiesta da XML a JSON, imposta semplicemente entrambi questi valori su request
.
Poiché vuoi convertire le risposte da XML a JSON, devi configurare un flusso di risposta condizionale per eseguire la conversione. Ad esempio, per convertire tutte le risposte da XML a JSON prima che vengano restituite all'app client, configura il seguente flusso di risposta ProxyEndpoint.
<Flows> <Flow name="Convert-for-devices"> <Response> <Step><Name>ConvertToJSON</Name></Step> </Response> </Flow> </Flows>
Quando richiami l'API utilizzando la richiesta standard, la risposta è formattata in JSON.
Tuttavia, il tuo obiettivo è convertire i report meteo in JSON solo quando il client richiedente è un dispositivo mobile. Per attivare questo comportamento dinamico, devi aggiungere un'istruzione condizionale al flusso.
Testa il flusso condizionale
In questa richiesta di esempio, l'intestazione HTTP User-Agent
è impostata su
Mozilla
, il che fa sì che l'istruzione condizionale venga valutata come true e il flusso
condizionale Convert-for-devices
venga eseguito.
curl -H "User-Agent:Mozilla" http://example.com/weather/forecastrss?w=12797282
oppure, per la formattazione del codice, se Python è disponibile:
curl -H "User-Agent:Mozilla" http://example.com/weather/forecastrss?w=12797282 | python -mjson.tool
Risposta di esempio:
. . . "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" } ] } . . .
Una richiesta inviata senza l'intestazione User-Agent
o con un valore diverso da Mozilla
genererà una risposta in formato XML.
$ curl http://example.com/weather/forecastrss?w=12797282
Viene restituita la risposta XML non modificata.
Risposta di esempio:
<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" />
Corrispondenza di pattern
Questa sezione descrive come utilizzare la corrispondenza dei pattern con le condizioni in un flusso Apigee.
Operatori
Questa sezione descrive come utilizzare i seguenti operatori di corrispondenza dei pattern negli statement condizionali:
- Operatore
Matches
: semplice corrispondenza di pattern - Operatore JavaRegex: controllo più preciso della corrispondenza
- Operatore
MatchesPath
: corrispondenza del frammento di percorso
Corrisponde a
Diamo prima un'occhiata all'operatore condizionale Matches
o ~
. Questi due operatori sono uguali: la versione in inglese, Matches
, è considerata un'opzione più leggibile.
Riepilogo: l'operatore Matches
offre due possibilità. Corrisponde alla
stringa in modo letterale o esegui una corrispondenza con caratteri jolly con *
. Come previsto, il carattere jolly corrisponde a zero
o più caratteri. Vediamo come funziona.
Il seguente XML mostra una condizione di passaggio. Esegue il criterio SomePolicy quando la condizione
ha valore true. In questo esempio, testiamo la variabile proxy.pathsuffix
, una variabile integrata in Apigee che memorizza il suffisso del percorso della richiesta. Tieni presente, tuttavia, che puoi verificare il valore di qualsiasi variabile di flusso contenente una stringa. Pertanto, in questo caso, se il percorso di base della richiesta in entrata è /animals
e la richiesta è /animals/cat
, il suffisso del percorso è la stringa letterale /cat
.
<PreFlow name="PreFlow"> <Request> <Step> <Condition>(proxy.pathsuffix Matches "/cat")</Condition> <Name>SomePolicy</Name> </Step> </Request> <Response/> </PreFlow>
Domanda: quale suffisso del percorso del proxy causerà l'esecuzione di SomePolicy? Esiste una sola possibilità.
Chiamata API:
GET http://example.com/matchtest/cat
Il criterio viene eseguito? Sì, perché il suffisso del percorso del proxy corrisponde esattamente a /cat
. Non verrà eseguito se il suffisso è /bat
o /dog
o
/
o qualsiasi altro.
Ora, considera questa istruzione condizionale in cui utilizziamo il carattere jolly
*
:
<Condition>(proxy.pathsuffix Matches "/*at")</Condition>
Chiamata API:
GET http://example.com/matchtest/cat
Il criterio viene eseguito? Sì, perché il carattere jolly corrisponde a qualsiasi carattere e ""/cat
" è una corrispondenza.
Chiamata API:
GET http://example.com/matchtest/bat
Il criterio viene eseguito? Sì, perché il carattere jolly corrisponde a qualsiasi carattere, "/bat"
è una corrispondenza.
Chiamata API:
GET http://example.com/matchtest/owl
Il criterio viene eseguito? Assolutamente no. Anche se il carattere jolly corrisponde a o
,
le lettere wl
non corrispondono.
Ora spostiamo il carattere jolly alla fine del suffisso:
<Condition>(proxy.pathsuffix Matches "/cat*")</Condition>
Chiamata API:
GET http://example.com/matchtest/cat
Il criterio viene eseguito? Sì, perché il carattere jolly corrisponde a zero o più caratteri qualsiasi.
Chiamata API:
GET http://example.com/matchtest/bat
Il criterio viene eseguito? No, /bat
non è una corrispondenza.
Chiamata API:
GET http://example.com/matchtest/cat123
Il criterio viene eseguito? Sì, il carattere jolly corrisponde a zero o più caratteri, pertanto
123
genera una corrispondenza.
Chiamata API:
GET http://example.com/matchtest/cat/bird/mouse
Il criterio viene eseguito? Sì, perché il carattere jolly corrisponde a zero o più caratteri qualsiasi, quindi
/bird/mouse
genera una corrispondenza. Tieni presente che un'espressione come questa può metterti nei guai perché corrisponde a tutto ciò che segue i caratteri letterali.
Domanda: l'operatore Matches
è sensibile alle maiuscole?
Sì. Supponiamo che tu abbia una condizione come questa:
<Condition>(proxy.pathsuffix Matches "/*At")</Condition>
Chiamata API:
GET http://example.com/matchtest/cat
Il criterio viene eseguito? No, il carattere jolly corrisponde a qualsiasi lettera (indipendentemente dalle maiuscole), ma la lettera a
minuscola non corrisponde a A
.
Chiamata API:
GET http://example.com/matchtest/bAt
Il criterio viene eseguito? Sì, la custodia corrisponde.
Domanda: come faccio a eseguire l'escapismo dei caratteri con l'operatore Matches
?
Utilizza il carattere percentuale %
per inserire caratteri di escape per i caratteri riservati. Ad esempio:
<Condition>(proxy.pathsuffix Matches "/c%*at")</Condition>
Chiamata API:
GET http://example.com/matchtest/cat
Il criterio viene eseguito? No, l'operatore Matches
cerca la stringa letterale
c*at
.
Chiamata API:
GET http://example.com/matchtest/c*at
Domanda:il criterio viene eseguito?
Sì, questo percorso, anche se un po' insolito, corrisponde.
JavaRegex
Come puoi vedere, l'operatore Matches
è ideale per situazioni semplici. Tuttavia, puoi utilizzare un altro operatore, JavaRegex o ~~
. Si tratta dello stesso operatore, tranne per il fatto che JavaRegex è considerato più leggibile. Si chiama JavaRegex perché consente la corrispondenza di pattern con espressioni regolari e Apigee segue le stesse regole delle classi nel package java.util.regex nel linguaggio Java. Il funzionamento dell'operatore JavaRegex è molto diverso da quello dell'operatore Matches
, quindi è importante non confondere i due.
Riepilogo: l'operatore JavaRegex ti consente di utilizzare la sintassi delle espressioni regolari negli statement condizionali.
Il seguente codice mostra una condizione Passaggio. Viene eseguito il criterio SomePolicy se la condizione
restituisce true
. In questo esempio, testiamo la variabile proxy.pathsuffix
, una variabile interna di Apigee che memorizza il suffisso del percorso della richiesta. Se il percorso di base della richiesta in entrata è /animals
e la richiesta è /animals/cat
, il suffisso del percorso è la stringa letterale /cat
.
<PreFlow name="PreFlow"> <Request> <Step> <Condition>(proxy.pathsuffix JavaRegex "/cat")</Condition> <Name>SomePolicy</Name> </Step> </Request> <Response/> </PreFlow>
Domanda: quale suffisso del percorso del proxy causerà l'esecuzione di SomePolicy? Come accade con l'operatore Matches
, in questo caso esiste una sola possibilità.
Chiamata API:
GET http://example.com/matchtest/cat
Il criterio viene eseguito? Sì, perché il suffisso del percorso del proxy corrisponde esattamente a /cat
. Non verrà eseguito se il suffisso è /bat
o /dog
o qualcos'altro.
Ora creiamo un'espressione regolare utilizzando il quantificatore *
. Questo quantificatore corrisponde a zero o più caratteri precedenti.
<Condition>(proxy.pathsuffix JavaRegex "/c*t")</Condition>
Chiamata API:
GET http://example.com/matchtest/cat
Il criterio viene eseguito? No! Il quantificatore *
corrisponde a zero o più caratteri precedenti, ovvero un c
.
Chiamata API:
GET http://example.com/matchtest/ccccct
Il criterio viene eseguito? Sì, perché il carattere jolly corrisponde a zero o più caratteri che lo precedono.
Successivamente, utilizziamo il quantificatore ?
, che corrisponde al carattere precedente una volta o per niente.
<Condition>(proxy.pathsuffix JavaRegex "/ca?t")</Condition>
Chiamata API:
GET http://example.com/matchtest/cat
Il criterio viene eseguito? Sì. Il quantificatore ?
corrisponde a zero o una occorrenza del carattere precedente, ovvero un a
.
Chiamata API:
GET http://example.com/matchtest/ct
Il criterio viene eseguito? Sì. Il quantificatore ?
corrisponde a uno o
nessuno dei caratteri precedenti. In questo caso, non è presente il carattere a
, pertanto la condizione viene valutata come true
.
Chiamata API:
GET http://example.com/matchtest/caat
Il criterio viene eseguito? No. Il quantificatore ?
corrisponde a uno dei caratteri che lo precede, ovvero un a
.
Successivamente, utilizziamo lo stile di espressione regex [abc]
o di raggruppamento. Corrisponde ai caratteri a
, b
o c
.
<Condition>(proxy.pathsuffix JavaRegex "/[cbr]at")</Condition>
Chiamata API:
GET http://example.com/matchtest/cat
Il criterio viene eseguito? Sì. Qui utilizziamo espressioni regolari e l'espressione [cbr]
corrisponde a c
, b
o r
. Queste chiamate sono anche corrispondenze:
GET http://example.com/matchtest/bat
GET http://example.com/matchtest/rat
Ma non è una corrispondenza:
GET http://example.com/matchtest/mat
Domanda: l'operatore JavaRegex è sensibile alle maiuscole?
Sì. Supponiamo che tu abbia una condizione come questa:
<Condition>(proxy.pathsuffix JavaRegex "/ca?t")</Condition>
Chiamata API:
GET http://example.com/matchtest/cat
Il criterio viene eseguito? Sì, la regex corrisponde a zero o a uno dei caratteri precedenti, ovvero a
.
Chiamata API:
GET http://example.com/matchtest/cAt
Domanda: il criterio viene eseguito?
No, perché la lettera maiuscola A
non corrisponde alla lettera minuscola a
.
MatchesPath
L'operatore MatchesPath
può essere specificato anche in questo modo ~/
. Ha un aspetto simile agli operatori Matches
(~
) e JavaRegex (~~
). Ma
MatchesPath
è completamente diverso.
Ricorda che questo operatore considera un percorso come una serie di parti. Pertanto, se il percorso è /animals/cats/wild
, puoi immaginarlo come costituito dalle parti /animals
, /cats
e /wild
.
L'operatore MatchesPath
consente di utilizzare due notazioni di caratteri jolly: un singolo asterisco (*) e un asterisco doppio (**
). Il singolo asterisco corrisponde a un elemento del percorso. Il doppio asterisco corrisponde a uno o più elementi del percorso.
Vediamo un esempio. In questo esempio, testiamo la variabile proxy.pathsuffix
,
una variabile integrata in Apigee che memorizza il suffisso del percorso della richiesta. Tieni presente, tuttavia, che puoi verificare il valore di qualsiasi variabile di flusso contenente una stringa.
<PreFlow name="PreFlow"> <Request> <Step> <Condition>(proxy.pathsuffix MatchesPath "/animals/*")</Condition> <Name>SomePolicy</Name> </Step> </Request> <Response/> </PreFlow>
Domanda: quale suffisso del percorso del proxy causerà l'esecuzione di SomePolicy?
Chiamata API:
GET http://example.com/matchtest/animals
Domanda: il criterio viene eseguito?
No, perché la condizione richiede un altro elemento di percorso dopo
/animals
, come specificato da /*
.
Chiamata API:
GET http://example.com/matchtest/animals
/
Il criterio viene eseguito? Sì, il percorso ha un altro elemento (la parte dopo
/animals/
), ma è vuoto.
Chiamata API:
GET http://example.com/matchtest/animals/cats
Il criterio viene eseguito? Sì, perché il percorso contiene chiaramente un elemento (/cats
)
che segue /animals
Chiamata API:
GET http://example.com/matchtest/animals/cats/wild
Domanda: il criterio viene eseguito?
No, perché l'asterisco singolo corrisponde a un solo elemento del percorso e questa API ha più di un elemento dopo /animals
.
Ora utilizziamo il doppio asterisco:
<PreFlow name="PreFlow"> <Request> <Step> <Condition>(proxy.pathsuffix MatchesPath "/animals/**")</Condition> <Name>SomePolicy</Name> </Step> </Request> <Response/> </PreFlow>
Domanda: quale suffisso del percorso del proxy causerà l'esecuzione di SomePolicy?
Chiamata API:
GET http://example.com/matchtest/animals
Il criterio viene eseguito? No, perché la condizione richiede almeno un elemento del percorso successivo
specificato da /**
.
Chiamata API:
GET http://example.com/matchtest/animals
/
Il criterio viene eseguito?
Sì, il percorso ha un altro elemento (la parte dopo
/animals/
), ma è vuoto.
Chiamata API:
GET http://example.com/matchtest/animals/cats
Il criterio viene eseguito?
Sì, perché il percorso contiene almeno un elemento successivo a /animals
Chiamata API:
GET http://example.com/matchtest/animals/cats/wild
Il criterio viene eseguito?
Sì, perché il percorso contiene più di un elemento successivo
/animals
Asterischi misti
Puoi utilizzare combinazioni di asterischi singoli (*) e doppi (**) per perfezionare ulteriormente la corrispondenza dei percorsi.
<PreFlow name="PreFlow"> <Request> <Step> <Condition>(proxy.pathsuffix MatchesPath "/animals/*/wild/**")</Condition> <Name>SomePolicy</Name> </Step> </Request> <Response/> </PreFlow>
Chiamata API:
Tutte queste chiamate API produrranno una corrispondenza:
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
Risorse API
I servizi RESTful sono raccolte di risorse API. Una risorsa API è un frammento di percorso URI che identifica un'entità a cui gli sviluppatori possono accedere chiamando la tua API. Ad esempio, se il tuo servizio fornisce report meteo e previsioni meteo, il servizio di backend potrebbe definire due risorse API:
http://mygreatweatherforecast.com/reports
http://mygreatweatherforecast.com/forecasts
Quando crei un proxy API (come mostrato in Creare il tuo primo proxy API), crei almeno un URL di base dell'alias che mappa al tuo servizio di backend. Ad esempio:
URL di base del backend | URL del proxy API nuovo/equivalente |
---|---|
http://mygreatweatherforecast.com |
http://example.com/mygreatweatherforecast |
A questo punto puoi effettuare chiamate API al tuo backend utilizzando uno dei due URL di base. Ma quando utilizzi l'URL del proxy API, le cose iniziano a farsi interessanti.
Oltre ai dati e alle analisi API che Apigee inizia a raccogliere quando utilizzi il proxy API, i proxy consentono anche di definire flussi condizionali che si mappano alle risorse nel tuo backend. In sostanza, se viene inviata una chiamata GET
alla risorsa /reports
, Apigee deve fare qualcosa.
L'immagine seguente mostra la differenza di comportamento tra due URL che accedono allo stesso backend. Uno è l'URL della risorsa senza proxy, l'altro è un proxy API Apigee con un flusso condizionale alla stessa risorsa di backend. Di seguito descriveremo i flussi condizionali in modo più dettagliato.
Come i proxy API vengono mappati a risorse di backend specifiche
Con un URL proxy API mappato all'URL base del servizio di backend (quando crei il proxy), puoi aggiungere flussi condizionali a risorse specifiche, come le risorse /reports
e /forecasts
menzionate in precedenza.
Supponiamo che tu voglia che Apigee faccia qualcosa quando arrivano chiamate alle risorse /reports
o /forecasts
. A questo punto non stai dicendo ad Apigee
cosa fare, ma solo che deve ascoltare le chiamate a queste risorse. Per farlo,
utilizza le condizioni. Nel proxy API Apigee, puoi creare flussi condizionali per /reports
e /forecasts
. A scopo concettuale, il seguente XML del proxy API mostra come potrebbero essere queste condizioni.
<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>
Queste condizioni indicano che quando viene inviata una richiesta GET
con /reports
e
/forecasts
nell'URL, Apigee eseguirà qualsiasi istruzione fornita da te (lo sviluppatore dell'API),
tramite i criteri che colleghi a questi flussi.
Ecco un esempio di come dire ad Apigee cosa fare quando viene soddisfatta una condizione. Nel seguente XML del proxy API, quando viene inviata una richiesta GET
a https://example.com/mygreatweatherforecast/reports
, Apigee esegue il criterio XML-to-JSON-1
nella risposta.
<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>
Oltre a questi flussi condizionali facoltativi, ogni proxy API è dotato anche di due flussi predefinite: un <PreFlow>
eseguito prima dei flussi condizionali e un <PostFlow>
eseguito dopo i flussi condizionali. Questi sono utili per eseguire i criteri quando viene effettuata qualsiasi chiamata a un proxy API. Ad esempio, se vuoi verificare la chiave API di un'app a ogni chiamata, indipendentemente dalla risorsa di backend a cui viene eseguito l'accesso, puoi impostare un criterio Verifica chiave API su <PreFlow>
. Per saperne di più sui flussi, consulta
Configurare i flussi.
Crea flussi condizionali alle risorse di backend
La definizione di flussi condizionali alle risorse di backend in un proxy API è completamente facoltativa. Tuttavia, questi flussi condizionali ti consentono di applicare una gestione e un monitoraggio granulari.
Potrai:
- Applica la gestione in modo che rifletta la semantica del modello dell'API
- Applicare criteri e comportamento basato su script a singoli percorsi delle risorse (URI)
- Raccogliere metriche granulari per i servizi Analytics
Ad esempio, immagina di dover applicare diversi tipi di logica al tuo backend
alle risorse /developers
e /apps
.
Per farlo, aggiungi due flussi condizionali nel proxy API: /developers
e
/apps
.
Nuovo editor proxy
Per aggiungere un flusso condizionale:
- Seleziona la scheda Sviluppa in Proxy Editor.
- Seleziona Endpoint proxy > predefinito nel riquadro a sinistra.
- Fai clic sul pulsante + sopra il riquadro Risposta.
- Nella finestra di dialogo Aggiungi flusso condizionale, inserisci le seguenti configurazioni:
- Nome flusso:
Developers
- Tipo di condizione:
Path
- Percorso:
/developers
La condizione verrà attivata (e i criteri verranno eseguiti) se viene inviata una chiamata al proxy con
/developers
alla fine dell'URI. - Nome flusso:
- Ora aggiungi un flusso condizionale per
/apps
e supponiamo che tu voglia che la condizione venga attivata sia sull'URI sia sul verboPOST
in una richiesta. La configurazione prevede l'impostazione di quanto segue:- Nome flusso:
Apps
- Tipo di condizione:
Path and Verb
- Percorso:
/apps
- Verbo:
POST
La condizione verrà attivata (e i criteri verranno eseguiti) se viene inviata una chiamata al proxy con
/apps
alla fine dell'URI e un verboPOST
. - Nome flusso:
I flussi aggiunti vengono visualizzati nel riquadro Risposta:
Editor proxy classico
Nel riquadro Sviluppa del riquadro Navigator dell'editor del proxy API, fai clic su accanto a predefinito in Endpoint proxy.
Nella finestra Nuovo flusso condizionale, inserisci le seguenti configurazioni chiave:
- Nome flusso:
Developers
- Tipo di condizione:
Path
- Percorso:
/developers
La condizione verrà attivata (e i criteri verranno eseguiti) se viene inviata una chiamata al proxy con /developers
alla fine dell'URI.
Ora aggiungi un flusso condizionale per /apps
e supponiamo che tu voglia che la condizione venga attivata sia sull'URI sia sul verbo POST
in una richiesta. La configurazione prevede l'impostazione di quanto segue:
- Nome flusso:
Apps
- Tipo di condizione:
Path and Verb
- Percorso:
/apps
- Verbo:
POST
La condizione verrà attivata (e i criteri verranno eseguiti) se viene inviata una chiamata al proxy con /apps
alla fine dell'URI e un verbo POST
.
Nel riquadro Navigator, vedrai nuovi flussi per App e Sviluppatori.
Seleziona uno dei flussi per visualizzare la configurazione del flusso condizionale nella visualizzazione del codice dell'editor del proxy 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>
Come puoi vedere, le risorse API sono semplicemente flussi agevolati che valutano il percorso URI della richiesta in entrata. La variabile proxy.pathsuffix
identifica l'URI della richiesta che segue
il BasePath configurato nella configurazione di ProxyEndpoint.
Ogni risorsa API che definisci viene implementata da un flusso condizionale nel proxy API. (Vedi Configurare i flussi.)
Dopo aver eseguito il deployment del proxy API nell'ambiente di test, la seguente richiesta:
http://example.com/PROXY_PATH/apps
La condizione verrà valutata come true
e questo flusso, insieme a eventuali criteri associati, verrà eseguito.
La seguente condizione di esempio utilizza un'espressione regolare Java per riconoscere le chiamate effettuate alla risorsa /apps
con o senza una barra verticale finale (/apps
o /apps/**
):
<Condition>(proxy.pathsuffix JavaRegex "/apps(/?)") and (request.verb = "POST")</Condition>
Per saperne di più su questo tipo di condizione, consulta Come eseguire la corrispondenza indipendentemente dal fatto che sia presente o meno un "/" finale… nella community Apigee.
Modellazione di URI gerarchici
In alcuni casi, avrai risorse API gerarchiche. Ad esempio, l'API Developer Apps List fornisce un metodo per elencare tutte le app appartenenti a uno sviluppatore. Il percorso dell'URI è:
/developers/DEVELOPER_EMAIL/apps
Potresti avere risorse in cui viene generato un ID univoco per ogni entità di una raccolta, che talvolta viene annotata come segue:
/genus/:id/species
Questo percorso si applica allo stesso modo ai seguenti due URI:
/genus/18904/species /genus/17908/species
Per rappresentare questa struttura in una risorsa API, puoi utilizzare i caratteri jolly. Ad esempio:
/developers/*/apps /developers/*example.com/apps /genus/*/species
Questi risolveranno gli URI gerarchici come risorse API in modo appropriato.
In alcuni casi, in particolare per le API gerarchiche complesse, potresti semplicemente voler risolvere tutto ciò che si trova sotto un determinato frammento URI. A tal fine, utilizza un asterisco doppio jolly nella definizione della risorsa. Ad esempio, se definisci la seguente risorsa API:
/developers/**
Questa risorsa dell'API risolverà i seguenti percorsi URI:
/developers/DEVELOPER_EMAIL/apps /developers/DEVELOPER_EMAIL/keys /developers/DEVELOPER_EMAIL/apps/APP_ID/keys
Ecco come appare la condizione di flusso condizionale nella definizione del proxy API:
<Condition>(proxy.pathsuffix MatchesPath "/developers/**") and (request.verb = "POST")</Condition>
Altri esempi
Condizione associata 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>
Condizione associata a un criterio
<Step> <!--the policy MaintenancePolicy only executes if the response status code is exactly 503 --> <Condition>response.status.code = 503</Condition> <Name>MaintenancePolicy</Name> </Step>
Flusso condizionale
<!-- 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>
Operatori di esempio nelle condizioni
Ecco alcuni esempi di operatori utilizzati per creare condizioni:
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
Un esempio pratico: ignora/
alla fine di un percorso
Gli sviluppatori Apigee in genere vogliono gestire entrambi i suffissi del percorso: /cat
e
/cat/
. Questo perché alcuni utenti o client potrebbero chiamare la tua API con la barra aggiuntiva alla fine del percorso e devi essere in grado di gestirla nelle tue istruzioni condizionali. Questo caso d'uso esatto è stato discusso in
come eseguire la corrispondenza indipendentemente dal fatto che nell'URL sia presente o meno un carattere "/" finale.
Se preferisci, puoi ottenere questo risultato senza utilizzare Regex come segue:
<PreFlow name="PreFlow"> <Request> <Step> <Condition>(proxy.pathsuffix = "/cat") OR (proxy.pathsuffix = "/cat/")</Condition> <Name>SomePolicy</Name> </Step> </Request> <Response/> </PreFlow>
Questa è una buona opzione. Sia chiaro e leggibile.
Tuttavia, puoi fare la stessa cosa con le regex, come mostrato di seguito. Le parentesi vengono utilizzate per raggruppare la parte regex dell'istruzione, ma non sono obbligatorie.
<Condition>(proxy.pathsuffix JavaRegex "/cat(/?)"</Condition>
Chiamate API:
GET http://example.com/matchtest/cat
or GET http://example.com/matchtest/cat
/
Il criterio viene eseguito? Sì. Tieni presente che in un'espressione regolare, il carattere ?
significa: corrisponde a zero o a uno dei caratteri precedenti. Pertanto, sia /cat
sia /cat/
sono corrispondenze.
Chiamata API:
GET http://example.com/matchtest/cat/spotted
Il criterio viene eseguito? No. L'espressione regolare corrisponde a zero o a una sola occorrenza del carattere precedente e non è consentito altro.
Corrispondenza di stringhe arbitrarie con JavaRegex
In tutti gli esempi di questo argomento viene mostrato come associare una delle variabili di flusso predefinite:
proxy.pathsuffix
. È bene sapere che puoi eseguire la corrispondenza di pattern su qualsiasi stringa arbitraria o variabile di flusso, indipendentemente dal fatto che si tratti di una variabile di flusso integrata come proxy.pathsuffix
.
Ad esempio, se hai una condizione che testa una stringa arbitraria, ad esempio una stringa restituita
in un payload di backend o una stringa restituita da una ricerca del server di autenticazione, puoi utilizzare
gli operatori di corrispondenza per testarla. Se utilizzi JavaRegex
, l'espressione regolare verrà confrontata con l'intera stringa dell'oggetto. Se l'oggetto è abc
e l'espressione regolare è [a-z]
,
non esiste alcuna corrispondenza, perché [a-z]
corrisponde esattamente a un carattere alfa. L'espressione [a-z]+
funziona, così come [a-z]*
e [a-z]{3}
.
Vediamo un esempio concreto. Supponiamo che il server di autenticazione restituisca un elenco di ruoli come
una stringa separata da virgole: editor, author, guest
.
Per testare la presenza del ruolo di editor, questa costruzione non funzionerà, perché editor
è solo parte dell'intera stringa.
<Condition>returned_roles ~~ "editor"</Condition>
Tuttavia, questa costruzione funzionerà:
<Condition>returned_roles ~~ ".*\beditor\b.*")</Condition>
Funziona perché tiene conto degli a capo e di eventuali altre parti della stringa con il prefisso e il suffisso .*
.
In questo esempio, puoi anche verificare la presenza di editor
con l'operatore Matches
:
<Condition>returned_roles ~~ "*editor*")</Condition>
Tuttavia, nei casi in cui hai bisogno di una maggiore precisione, JavaRegex è spesso una scelta migliore.
Escrezione delle virgolette doppie nelle espressioni JavaRegex
La sintassi della condizione richiede che un'espressione JavaRegex sia racchiusa tra virgolette doppie. Pertanto, se hai un'espressione regex che include virgolette doppie, devi trovare un modo alternativo per creare una corrispondenza. La risposta è Unicode. Ad esempio, supponiamo che tu passi un'intestazione che includa virgolette doppie, come la seguente:
-H 'content-type:multipart/related; type="application/xop+xml"'
Se provi a trovare una corrispondenza per l'intestazione in una condizione regex, verrà visualizzato un errore Invalid Condition
perché l'espressione include le virgolette doppie:
request.header.Content-Type ~~ "(multipart\/related)(; *type="application\/xop\+xml\")"
La soluzione consiste nel sostituire le virgolette doppie basate su ASCII con l'equivalente Unicode, \u0022
. Ad esempio,
la seguente espressione è valida e produce il risultato previsto:
request.header.Content-Type ~~ "(multipart\/related)(; *type=\u0022application\/xop\+xml\u0022)"