Condizioni con variabili di flusso

Questa pagina si applica a Apigee e Apigee ibrido.

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 RouteRules. Se definisci istruzioni condizionali, definisci il comportamento dinamico per l'API. Questo comportamento dinamico ti consente, ad esempio, di convertire un file XML in JSON solo per i dispositivi mobili o di eseguire il routing a un URL di backend in base al tipo di contenuti o al verbo HTTP del messaggio della richiesta.

Questo argomento mostra come utilizzare le condizioni per applicare dinamicamente le funzionalità di gestione delle API in fase di runtime, senza scrivere alcun codice.

Configurare istruzioni condizionali

Il comportamento condizionale viene implementato nei proxy API utilizzando una combinazione di conditions e conditions. 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), != (diverso da) e > (maggiore di). Per una migliore leggibilità, puoi anche scrivere le condizionali come testo: equals, notequals, greaterthan.

Quando lavori con i percorsi URI, puoi utilizzare ~/ o MatchesPath. Puoi anche abbinare le espressioni regolari JavaRegex con l'operatore ~~.

Le condizioni vengono utilizzate per definire i flussi condizionali del proxy API verso le risorse dell'API backend, descritto in Creare flussi condizionali verso le risorse dell'API backend. Per un elenco completo delle condizionali, consulta Riferimento alle condizioni.

Variabili

Le condizioni svolgono il proprio lavoro valutando i valori delle variabili. Una variabile è una proprietà di una transazione HTTP eseguita da un proxy API o una proprietà della configurazione stessa del proxy API. Ogni volta che un proxy API riceve una richiesta da un'app, Apigee compila un lungo elenco di variabili associate a elementi come l'ora di sistema, le informazioni di rete dell'app, le intestazioni HTTP dei messaggi, la configurazione del proxy API, le esecuzioni dei criteri e così via. Ciò crea un contesto dettagliato che puoi utilizzare per configurare dichiarazioni condizionali.

Le variabili utilizzano sempre una notazione puntata. Ad esempio, le intestazioni HTTP nel messaggio di richiesta sono disponibili come variabili chiamate request.header.HEADER_NAME. Pertanto, per valutare Content-type header, potresti utilizzare la variabile request.header.Content-type. Ad esempio, request.header.Content-type = "application/json" indica che il tipo di contenuto della richiesta deve essere JSON.

Immagina di dover creare un'istruzione condizionale che causerà l'applicazione forzata di un criterio solo quando un messaggio di richiesta è un GET. Per creare una condizione che valuti il verbo HTTP di una richiesta, crea l'istruzione condizionale 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 precedente restituisce true se il verbo HTTP associato alla richiesta è GET. Se il verbo HTTP associato alla richiesta è POST, l'istruzione restituisce un valore false.

Per abilitare il comportamento dinamico, puoi collegare delle condizioni a Flussi, Passi e RouteRules.

Quando colleghi una condizione a un flusso, crei un flusso condizionale. I flussi condizionali vengono eseguiti solo quando la condizione è true. Puoi collegare tutti i criteri che vuoi a un flusso condizionale. Un flusso condizionale consente di creare regole di elaborazione altamente specializzate per messaggi di richiesta o risposta che soddisfano determinati criteri.

Ad esempio, per creare un flusso che viene eseguito solo quando il verbo di 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 relativo alle norme stesso. La seguente condizione fa sì che il criterioVerifyAPIKey venga applicato in modo forzato solo se un messaggio di richiesta è 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 collegare i criteri ai flussi, abilitando un proxy API per 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 la condizione. 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 archivia i valori di tutte le intestazioni HTTP presenti come variabili. Se la richiesta contiene un'intestazione HTTP denominata User-Agent, questa intestazione e il relativo valore vengono archiviati come una variabile denominata request.header.User-Agent.

Data la configurazione ProxyEndpoint riportata sopra, Apigee controlla il valore della variabile request.header.User-Agent per verificare se la condizione restituisce true.

Se la condizione restituisce true, ovvero il valore della variabile request.header.User-Agent è uguale a Mozilla, il flusso condizionale viene eseguito e viene applicato il criterio XMLtoJSON denominato ConvertToJSON. 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 a JSON, ma solo per i dispositivi mobili. Innanzitutto, crea il criterio che convertirà la risposta in formato XML dall'API Weather in JSON:

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

La configurazione dei criteri riportata sopra indica al proxy API di accettare il messaggio di risposta, eseguire una conversione da XML a JSON con le impostazioni predefinite e quindi scrivere il risultato nel nuovo messaggio di risposta. Se vuoi convertire un messaggio request da XML a JSON, devi semplicemente impostare 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 una richiesta standard, la risposta viene formattata in JSON.

Tuttavia, il tuo obiettivo è convertire le previsioni meteo in JSON solo quando il client richiedente è un dispositivo mobile. Per abilitare questo comportamento dinamico, devi aggiungere un'istruzione condizionale al flusso.

Testa il flusso condizionale

In questa richiesta di esempio, l'intestazione User-Agent HTTP è impostata su Mozilla, perciò l'istruzione condizionale restituisce il valore true e il flusso condizionale Convert-for-devices viene eseguito.

curl -H "User-Agent:Mozilla" http://example.com/weather/forecastrss?w=12797282

o per scrivere dove è disponibile Python:

curl -H "User-Agent:Mozilla" http://example.com/weather/forecastrss?w=12797282 | python -mjson.tool

Esempio di risposta:

. . .

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

Esempio di risposta:

<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 nelle istruzioni condizionali:

Corrisponde a

Esaminiamo prima l'operatore condizionale Matches o ~. Questi due operatori sono uguali. La versione inglese, Matches, è considerata un'opzione più leggibile.

Riepilogo:l'operatore Matches offre due possibilità. Puoi trovare una corrispondenza letterale con la stringa oppure creare una corrispondenza con caratteri jolly in *. Come ci si potrebbe aspettare, il carattere jolly corrisponde a zero o più caratteri. Vediamo come funziona.

Il seguente XML mostra una condizione Step. Esegue il criterio SomePolicy quando la condizione restituisce true. In questo esempio, testiamo la variabile proxy.pathsuffix, una variabile integrata in Apigee che archivia il suffisso del percorso della richiesta. Nota, tuttavia, puoi testare il valore di qualsiasi variabile di flusso contenente una stringa. Quindi, 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 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 proxy corrisponde esattamente a /cat. Non verrà eseguito se il suffisso è /bat o /dog, / o un altro.

Ora consideriamo 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ì, poiché il carattere jolly corrisponde a qualsiasi carattere, "/bat" è una corrispondenza.

Chiamata API:

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

Il criterio viene eseguito? Ovviamente no, anche se il carattere jolly corrisponde al 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.

Chiamata API:

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

Il criterio viene eseguito? No, /bat non corrisponde.

Chiamata API:

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

Il criterio viene eseguito? Sì, il carattere jolly corrisponde a zero o più caratteri, pertanto 123 produce 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, quindi /bird/mouse produce una corrispondenza. Nota come un'espressione come questa può metterti nei guai perché trova corrispondenze con tutto ciò che segue i caratteri letterali.

Domanda: l'operatore Matches è sensibile alle maiuscole?

Sì. Supponi di avere 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 il carattere a minuscolo non corrisponde a A.

Chiamata API:

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

Il criterio viene eseguito? Sì, la richiesta corrisponde.

Domanda: come faccio a inserire caratteri di escape con l'operatore Matches?

Utilizza il carattere % (percentuale) per eseguire l'escape dei 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 sta cercando 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 è ottimo per situazioni semplici. Tuttavia, puoi utilizzare un altro operatore, JavaRegex o ~~. Questi due sono lo stesso operatore, ad eccezione del 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 del pacchetto java.util.regex in linguaggio Java. Il funzionamento dell'operatore JavaRegex è molto diverso dall'operatore Matches, quindi è importante non confonderli.

Riepilogo: l'operatore JavaRegex consente di utilizzare la sintassi delle espressioni regolari nelle istruzioni condizionali.

Il seguente codice mostra una condizione Step. Esegue il criterio SomePolicy se la condizione restituisce true. In questo esempio, testiamo la variabile proxy.pathsuffix, una variabile integrata in Apigee che archivia 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 proxy causerà l'esecuzione di SomePolicy? Proprio come 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 proxy corrisponde esattamente a /cat. Non verrà eseguito se il suffisso è /bat, /dog o qualsiasi 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ù del carattere precedente, che è un c.

Chiamata API:

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

Il criterio viene eseguito? Sì, perché il carattere jolly corrisponde a zero o più dei caratteri precedenti.

Successivamente, utilizziamo il quantificatore ?, che corrisponde una volta sola al carattere precedente o non corrisponde affatto.

<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 a un'occorrenza del carattere precedente, che è un a.

Chiamata API:

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

Il criterio viene eseguito? Sì. Il quantificatore ? corrisponde a uno o nessuno del carattere precedente. In questo caso, non è presente alcun carattere a, quindi la condizione restituisce true.

Chiamata API:

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

Il criterio viene eseguito? No. Il quantificatore ? corrisponde a uno dei caratteri precedenti, che è un a.

Successivamente, utilizziamo lo stile [abc] o raggruppamento dell'espressione regex. 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, OR r. Queste chiamate corrispondono anche a:

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

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

Tuttavia, questa non è una corrispondenza:

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

Domanda: l'operatore JavaRegex è sensibile alle maiuscole?

Sì. Supponi di avere una condizione come questa:

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

Chiamata API:

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

Il criterio viene eseguito? Sì, l'espressione regolare corrisponde a zero o a uno dei caratteri precedenti, che è a.

Chiamata API:

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

Domanda: il criterio viene eseguito?

No, perché la A maiuscola non corrisponde alla lettera minuscola a.

MatchesPath

L'operatore MatchesPath può anche essere specificato in questo modo ~/. Ha un aspetto simile agli operatori Matches (~) e JavaRegex (~~). Tuttavia, MatchesPath è completamente diverso.

Ricorda solo che questo operatore considera un percorso come una serie di parti. Pertanto, se il percorso è: /animals/cats/wild, puoi pensare che sia composto da parti /animals, /cats e /wild.

L'operatore MatchesPath consente di utilizzare due notazioni con caratteri jolly: un singolo asterisco (*) e un doppio asterisco (**). Un 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 archivia il suffisso del percorso della richiesta. Nota, tuttavia, puoi testare 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 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 del percorso (la parte dopo /animals/), ma è semplicemente 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é il singolo asterisco corrisponde a un solo elemento del percorso e questa API ha più di un elemento dopo /animals.

Ora usiamo 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 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 di percorso seguente specificato da /**.

Chiamata API:

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

Il criterio viene eseguito?

Sì, il percorso ha un altro elemento del percorso (la parte dopo /animals/), ma è semplicemente vuoto.

Chiamata API:

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

Il criterio viene eseguito?

Sì, perché il percorso ha almeno un elemento che segue /animals

Chiamata API:

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

Il criterio viene eseguito?

Sì, perché il percorso ha più di un elemento che segue /animals

Combinazione di asterischi

Puoi utilizzare combinazioni di asterisco singolo (*) e doppio (**) per perfezionare ulteriormente la corrispondenza del percorso.

    <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 previsioni 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 Creazione del primo proxy API), come minimo stai creando un URL di base alias che è mappato 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 diventare interessanti.

Oltre all'analisi delle API che Apigee inizia a raccogliere quando utilizzi il proxy API, i proxy consentono anche di definire flussi condizionali che vengono mappati alle risorse sul tuo backend. In sostanza, se una chiamata GET arriva alla risorsa /reports, Apigee dovrebbe 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 maggiore dettaglio.

Per l&#39;URL proxy API Apigee con un flusso condizionale, la risposta converte il codice XML in JSON e raccoglie le analisi.

Mappatura dei proxy API a risorse di backend specifiche

Con un URL del proxy API mappato all'URL di base del servizio di backend (quando crei il proxy), puoi aggiungere flussi condizionali a risorse specifiche, ad esempio le risorse /reports e /forecasts menzionate in precedenza.

Supponiamo che tu voglia chiedere ad Apigee di fare qualcosa quando le chiamate arrivano alle risorse /reports o /forecasts. A questo punto non stai dicendo ad Apigee cosa fare, ma solo che dovrebbe ascoltare le chiamate a quelle risorse. Puoi farlo utilizzando delle 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 dicono: Quando una richiesta GET arriva con /reports e /forecasts nell'URL, Apigee farà ciò che dite tu (lo sviluppatore dell'API), attraverso i criteri che colleghi a questi flussi.

Ecco un esempio di come comunicare ad Apigee cosa fare quando una condizione è soddisfatta. Nel seguente codice 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 include anche due flussi predefiniti: un <PreFlow> eseguito prima dei flussi condizionali e un <PostFlow> eseguito dopo i flussi condizionali. Questi sono utili per l'esecuzione dei 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 si accede, potresti inserire un criterio di verifica della chiave API in <PreFlow>. Per scoprire di più sui flussi, consulta Configurazione dei flussi.

Creazione di flussi condizionali verso le risorse di backend

La definizione dei flussi condizionali verso le risorse di backend in un proxy API è completamente facoltativa. Tuttavia, questi flussi condizionali ti offrono la possibilità di applicare gestione e monitoraggio granulari.

Sarai in grado di:

  • Applica la gestione in modo che rifletta la semantica del tuo modello API
  • Applica criteri e comportamento basato su script a singoli percorsi di risorse (URI)
  • Raccogli metriche dettagliate per i servizi di analisi

Ad esempio, immagina di dover applicare diversi tipi di logica al backend /developers per le risorse /apps.

Per farlo, aggiungi due flussi condizionali nel proxy API: /developers e /apps.

Nuovo editor proxy

Per aggiungere un flusso condizionale:

  1. Seleziona la scheda Sviluppo nell'Editor proxy.
  2. Seleziona Endpoint del proxy > predefiniti nel riquadro a sinistra.

    Seleziona Endpoint proxy > default nel riquadro a sinistra.

  3. Fai clic sul pulsante + sopra il riquadro Risposta.

    Pulsante Aggiungi flusso condizionale

  4. Nella finestra di dialogo Add Conditional Flow (Aggiungi flusso condizionale), inserisci le seguenti configurazioni:
    • Nome flusso: Developers
    • Tipo di condizione: Path
    • Percorso: /developers

    Finestra di dialogo Aggiungi flusso condizionale.

    La condizione verrà attivata (e i criteri verranno eseguiti) se viene inviata una chiamata al proxy con /developers alla fine dell'URI.

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

I flussi aggiunti vengono visualizzati nel riquadro Risposta:

Finestra di dialogo Aggiungi flusso condizionale.

Editor proxy classico

Nel riquadro Sviluppo del riquadro Navigator dell'editor proxy API, fai clic su accanto a default in Proxy Endpoints.

Quando tieni il puntatore sul segno più accanto al valore predefinito, il testo visualizzato al passaggio del mouse è Aggiungi nuovo flusso.

Nella finestra New Conditional Flow, inserisci le seguenti configurazioni chiave:

  • Nome flusso: Developers
  • Tipo di condizione: Path
  • Percorso: /developers

Nel riquadro Nuovo flusso condizionale, viene configurato un flusso denominato Sviluppatori con la
    descrizione &quot;Sviluppatori di app registrati con i Servizi per gli sviluppatori&quot;.

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

Nel riquadro Nuovo flusso condizionale, viene configurato un flusso denominato App con la
    descrizione &quot;App sviluppatore registrate nei Servizi per gli sviluppatori&quot;.

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 Navigatore, vedrai nuovi flussi per App e Sviluppatori.

I nuovi flussi per app e sviluppatori sono visualizzati nel riquadro di navigazione sotto Endpoint proxy.

Seleziona uno dei flussi per visualizzare la configurazione del flusso condizionale nella visualizzazione codice dell'editor 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 condizionali che valutano il percorso dell'URI della richiesta in entrata. (La variabile proxy.pathsuffix identifica l'URI della richiesta che segue il BasePath configurato nella configurazione ProxyEndpoint.)

Ogni risorsa API che definisci viene implementata da un flusso condizionale nel proxy API. (Vedi Configurazione dei flussi.)

Dopo aver eseguito il deployment del proxy API nell'ambiente di test, inserisci la seguente richiesta:

http://example.com/PROXY_PATH/apps

farà sì che la condizione restituisca 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 (/apps o /apps/**):

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

Per ulteriori informazioni su questo tipo di condizione, consulta Come trovare una corrispondenza a prescindere dalla presenza di "/" ... nella community Apigee.

Modellazione di URI gerarchici

In alcuni casi, le risorse API saranno gerarchiche. Ad esempio, l'API Developer App list offre un metodo per elencare tutte le app di proprietà di 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 a volte viene annotato 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

che risolveranno in modo appropriato gli URI gerarchici come risorse API.

In alcuni casi, soprattutto per le API molto gerarchiche, potresti semplicemente voler risolvere tutto ciò che si trova al di sotto di un determinato frammento URI. Per farlo, utilizza un carattere jolly doppio asterisco nella definizione della risorsa. Ad esempio, se definisci la seguente risorsa API:

/developers/**

La risorsa API risolverà i seguenti percorsi URI:

/developers/DEVELOPER_EMAIL/apps
/developers/DEVELOPER_EMAIL/keys
/developers/DEVELOPER_EMAIL/apps/APP_ID/keys

Ecco come sarebbe la condizione del flusso condizionale nella definizione del proxy API:

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

Altri esempi

Condizione collegata 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 collegata 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 le 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 di solito preferiscono gestire entrambi i suffissi di percorso /cat e /cat/. Questo perché alcuni utenti o client potrebbero chiamare l'API con la barra aggiuntiva alla fine del percorso e tu devi essere in grado di gestire questa condizione nelle istruzioni condizionali. Questo caso d'uso esatto è stato discusso nella sezione Come trovare una corrispondenza a prescindere dalla presenza del carattere "/" finale nell'URL....

Se preferisci, puoi ottenere questo risultato senza utilizzare le espressioni regolari, come descritto di seguito:

    <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. È chiara e leggibile.

Puoi fare la stessa cosa con le espressioni regolari in questo modo. 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 che deve corrispondere a zero o a uno dei caratteri precedenti. Pertanto, /cat e /cat/ sono corrispondenze.

Chiamata API:

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

Il criterio viene eseguito? No. L'espressione regolare corrisponde a zero o solo a una occorrenza del carattere precedente. Non è consentito specificare nulla.

Corrispondenza di stringhe arbitrarie con JavaRegex

In tutti gli esempi in questo argomento, mostriamo come associare una delle variabili di flusso integrate: proxy.pathsuffix. È bene sapere che puoi eseguire la corrispondenza del pattern per qualsiasi stringa o variabile di flusso arbitraria, indipendentemente dal fatto che si tratti o meno di una variabile di flusso integrata come proxy.pathsuffix.

Se, ad esempio, hai una condizione che verifica una stringa arbitraria, ad esempio una stringa restituita in un payload del backend o una stringa restituita da una ricerca del server di autenticazione, puoi utilizzare gli operatori corrispondenti 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 c'è corrispondenza, perché [a-z] corrisponde esattamente a un carattere alpha. 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 stringa delimitata da una virgola: editor, author, guest.

Per testare la presenza del ruolo Editor, questa costruzione non funzionerà, perché editor è solo una parte dell'intera stringa.

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

Tuttavia, questa costruzione funzionerà:

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

Funziona perché tiene conto delle interruzioni di parola e di qualsiasi altra parte della stringa con il prefisso e il suffisso .*.

In questo esempio, puoi anche testare editor con l'operatore Matches:

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

Tuttavia, nei casi in cui è necessaria una maggiore precisione, JavaRegex è spesso una scelta migliore.

Uso di virgolette doppie nelle espressioni JavaRegex

La sintassi delle condizioni richiede che un'espressione JavaRegex sia racchiusa tra virgolette doppie; pertanto, se hai un'espressione regolare che include virgolette doppie, sarà necessario un modo alternativo per creare una corrispondenza. La risposta è Unicode. Ad esempio, supponiamo che tu passi un'intestazione che include virgolette doppie, come segue:

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

Se provi a trovare una corrispondenza per l'intestazione in una condizione regex, riceverai un errore Invalid Condition perché l'espressione include le virgolette:

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