Condiciones con variables de flujo

Estás consultando la documentación de Apigee Edge.
Consulta la documentación de Apigee X.
Información

Las sentencias condicionales son una estructura de control común en todos los lenguajes de programación. Al igual que un lenguaje de programación, la configuración del proxy de API admite sentencias condicionales para flujos, políticas, pasos y RouteRules. Con la definición de sentencias condicionales, se define el comportamiento dinámico de la API. Este comportamiento dinámico te permite realizar acciones como convertir XML en JSON solo para dispositivos móviles o enrutar a una URL de backend en función del tipo de contenido o el verbo HTTP del mensaje de la solicitud.

En este tema, se muestra cómo usar las sentencias para aplicar funciones de administración de API de forma dinámica en el entorno de ejecución sin escribir ningún código.

Configura sentencias condicionales

El comportamiento condicional se implementa en los proxies de API mediante una combinación de conditions y conditions. Una sentencia condicional se crea con un elemento de condición. La siguiente es una condición vacía:

<Condition></Condition>

Si quieres crear una sentencia condicional, agrega un operador condicional y una variable para crear la siguiente estructura:

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

Los operadores condicionales compatibles incluyen = (igual), != (no igual) y > (mayor que). Para facilitar la lectura, también puedes escribir los condicionales como texto: equals, notequals, greaterthan.

Cuando trabajas con rutas de URI, puedes usar ~/ o MatchesPath. También puedes hacer coincidir las expresiones regulares de JavaRegex con el operador ~~.

Las condiciones se usan para definir los flujos condicionales del proxy de API sobre los recursos de API de backend, que se describen en Crea flujos condicionales a recursos de API de backend. Para obtener una lista completa de condicionales, consulta Referencia de las condiciones.

Variables

El trabajo de las condiciones es evaluar los valores de las variables. Una variable es una propiedad de una transacción HTTP ejecutada por un proxy de API, o una propiedad de una configuración de proxy de API en sí. Cada vez que un proxy de API recibe una solicitud de una app, Apigee Edge propaga una larga lista de variables asociadas con aspectos como la hora del sistema, la información de red de la app, los encabezados HTTP en los mensajes, la configuración del proxy de la API, las ejecuciones de políticas, etcétera. Esto crea un contexto enriquecido que puedes usar para configurar declaraciones condicionales.

Las variables siempre usan una notación de puntos. Por ejemplo, los encabezados HTTP del mensaje de solicitud están disponibles como variables llamadas request.header.{header_name}. Por lo tanto, para evaluar el encabezado Content-type, podrías usar la variable request.header.Content-type. Por ejemplo, request.header.Content-type = "application/json" indica que el tipo de contenido de la solicitud debe ser JSON.

Imagina que necesitas crear una declaración condicional para que se aplique una política solo cuando un mensaje de solicitud sea GET. Para crear una condición que evalúe el verbo HTTP de una solicitud, crea la siguiente sentencia condicional. La variable en esta condición es request.verb. El valor de la variable es GET. El operador es =.

<Condition>request.verb = "GET"</Condition>
También puedes usar:
<Condition>request.verb equals "GET"</Condition>

Edge usa esa instrucción para evaluar las condiciones. El ejemplo anterior se evalúa como verdadero si el verbo HTTP asociado con la solicitud es GET. Si el verbo HTTP asociado con la solicitud es POST, la instrucción se evalúa como falsa.

Para habilitar el comportamiento dinámico, puedes adjuntar condiciones a los flujos, los pasos y las RouteRules.

Cuando adjuntas una condición a un flujo, se crea un “flujo condicional”. Los flujos condicionales solo se ejecutan cuando la condición se evalúa como verdadera. Puedes adjuntar tantas políticas como desees a un flujo condicional. Un flujo condicional te permite crear reglas de procesamiento altamente especializadas para mensajes de solicitud o respuesta que cumplan determinados criterios.

Por ejemplo, para crear un flujo que se ejecute solo cuando el verbo de solicitud es GET, haz lo siguiente:

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

Si deseas crear un flujo para las solicitudes GET y otro para las POST, sigue estos pasos:

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

Como se muestra en el siguiente ejemplo, puedes aplicar la condición al paso de política en sí. La siguiente condición hace que la política VerifyApiKey se aplique solo si un mensaje de solicitud es un POST.

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

Una vez que hayas definido esos flujos condicionales, puedes adjuntarles políticas, lo que permite que un proxy de API aplique un conjunto de políticas para las solicitudes GET y otro para las solicitudes POST.

Para obtener información de referencia completa, consulta los siguientes recursos:

Ejemplo 1

En el siguiente ejemplo, se muestra un solo flujo condicional llamado Convert-for-devices, configurado en el flujo de respuesta de ProxyEndpoint. Agrega la condición como elemento en la entidad a la que se aplica la condición. En este ejemplo, la condición es un componente del flujo. Por lo tanto, el flujo se ejecutará cada vez que la instrucción se evalúe como verdadera.

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

Para cada solicitud recibida de una app, Edge almacena los valores de todos los encabezados HTTP presentes como variables. Si la solicitud contiene un encabezado HTTP llamado User-Agent, ese encabezado y su valor se almacenan como una variable llamada request.header.User-Agent.

Dada la configuración de ProxyEndpoint anterior, Edge verifica el valor de la variable request.header.User-Agent para ver si la condición se evalúa como verdadera.

Si la condición se evalúa como verdadera, es decir, el valor de la variable request.header.User-Agent es igual a Mozilla, se ejecuta el flujo condicional y se aplica la política XMLtoJSON llamada ConvertToJSON. De lo contrario, el flujo no se ejecuta y la respuesta XML se muestra sin modificar (en formato XML) a la app solicitante.

Ejemplo 2

Veamos un ejemplo específico en el que necesitas transformar el mensaje de respuesta de XML a JSON, pero solo para dispositivos móviles. Primero, crea la política que convertirá la respuesta con formato XML de la API de Weather a JSON:

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

La configuración de política anterior indica al proxy de la API que tome el mensaje de respuesta, realice una conversión de XML a JSON con la configuración predeterminada y, luego, escriba el resultado en el nuevo mensaje de respuesta. Si quieres convertir un mensaje request de XML a JSON, solo debes establecer ambos valores como request.

Dado que deseas convertir las respuestas de XML a JSON, debes configurar un flujo de respuesta condicional para realizar la conversión. Por ejemplo, para convertir todas las respuestas de XML a JSON antes de que se muestren en la aplicación cliente, configura el siguiente flujo de respuesta ProxyEndpoint.

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

Cuando invocas la API mediante la solicitud estándar, la respuesta tiene el formato JSON.

Sin embargo, tu objetivo solo es convertir los informes de Weather a JSON cuando el cliente solicitante es un dispositivo móvil. Para habilitar este comportamiento dinámico, debes agregar una sentencia condicional al flujo.

Prueba el flujo condicional

En esta solicitud de muestra, el encabezado HTTP User-Agent se establece en Mozilla, lo que hace que la sentencia condicional se evalúe como verdadera y el flujo condicional Convert-for-devices se ejecute.

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

O hace que se imprima con formato estilístico si Python está disponible:

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

Respuesta de muestra:

. . .

"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 solicitud enviada sin el encabezado User-Agent o con un valor diferente a Mozilla, generará una respuesta con formato XML.

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

Se muestra la respuesta XML sin modificar.

Respuesta de muestra:

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

Coincidencia de patrones

En esta sección, se describe cómo usar la coincidencia de patrones con las condiciones en un flujo de Apigee.

Operadores

En esta sección, se describe cómo usar los siguientes operadores de coincidencia de patrones en las sentencias condicionales:

Mostrar coincidencias

Primero, veamos el operador condicional "Matches" o "~". Estos dos operadores son iguales: la versión en inglés, "Matches", se considera una opción más legible.

Resumen: El operador "Coincidencias" ofrece dos posibilidades. Haz una coincidencia literal con la string o haz una coincidencia de comodín con “*”. Como es de esperar, el comodín coincide con cero o más caracteres. Veamos cómo funciona este proceso.

El siguiente XML muestra una condición de paso. Ejecuta la política SomePolicy cuando la condición se evalúa como verdadera. En este ejemplo, probamos la variable proxy.pathsuffix, una variable integrada en Edge que almacena el sufijo de la ruta de acceso de la solicitud. Sin embargo, ten en cuenta que puedes probar el valor de cualquier variable de flujo que contenga una string. Por lo tanto, en este caso, si la ruta base de la solicitud entrante es /animals y la solicitud es /animals/cat, el sufijo de la ruta es la string literal "/cat".

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

Pregunta: ¿Qué sufijo de ruta del proxy hará que se ejecute SomePolicy? Solo hay una posibilidad.

Llamada a la API:

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

¿La política se ejecuta? Sí, porque el sufijo de la ruta de acceso del proxy coincide exactamente con “/cat”. No se ejecutará si el sufijo es /bat, /dog, "/" o cualquier otro.

Ahora, considera esta declaración condicional, en la que usamos el carácter comodín “*”:

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

Llamada a la API:

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

¿La política se ejecuta? Sí, porque el comodín coincide con cualquier carácter y "/cat" es una coincidencia.

Llamada a la API:

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

¿La política se ejecuta? Sí, porque el comodín coincide con cualquier carácter y "/bat" es una coincidencia.

Llamada a la API:

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

¿La política se ejecuta? Por supuesto que no. Aunque el comodín coincide con "o", las letras "wl" no coinciden.

Ahora, movamos el comodín al final del sufijo:

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

Llamada a la API:

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

¿La política se ejecuta? Sí, porque el comodín coincide con cero o más caracteres de cualquier tipo.

Llamada a la API:

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

¿La política se ejecuta? No, "/bat" no coincide.

Llamada a la API:

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

¿La política se ejecuta? Sí, el comodín coincide con cero o más caracteres, por lo que “123” genera una coincidencia.

Llamada a la API:

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

¿La política se ejecuta? Sí, porque el comodín coincide con cero o más caracteres, por lo que “/bird/mouse” produce una coincidencia. Ten en cuenta que una expresión como esta puede causar problemas, ya que coincide con todo lo que se encuentra después de los caracteres literales.

Pregunta: ¿El operador de coincidencias distingue mayúsculas de minúsculas?

Sí. Supongamos que tienes una condición como la que se muestra a continuación:

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

Llamada a la API:

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

¿La política se ejecuta? No, el comodín coincide con cualquier letra (sin importar el uso de mayúsculas o minúsculas), pero la “a” en minúscula no coincide con la “A”.

Llamada a la API:

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

¿La política se ejecuta? Sí, las mayúsculas coinciden.

Pregunta: ¿Cómo puedo escapar caracteres con el operador de coincidencias?

Usa el carácter de porcentaje “%” para escapar los caracteres reservados. Por ejemplo:

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

Llamada a la API:

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

¿La política se ejecuta? No, el operador de coincidencias busca la string literal "c*at".

Llamada a la API:

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

Pregunta: ¿La política se ejecuta?

Sí, esta ruta coincide, pese a ser algo inusual.

JavaRegex

Como puedes ver, el operador "Coincidencias" es excelente para situaciones simples. Sin embargo, puedes usar otro operador, "JavaRegex" o "~~". Estos dos son el mismo operador, pero se considera que JavaRegex es más legible. Se llama JavaRegex porque permite la coincidencia de patrones de expresiones regulares, y Edge sigue las mismas reglas que las clases en el paquete java.util.regex en el lenguaje Java. El funcionamiento del operador JavaRegex es muy diferente del operador Matches, por lo que es importante no confundirlos.

Resumen: El operador "JavaRegex" te permite usar la sintaxis de expresiones regulares en sentencias condicionales.

El siguiente código muestra una condición de paso. Ejecuta la política SomePolicy si la condición se evalúa como verdadera. En este ejemplo, probamos la variable proxy.pathsuffix, una variable integrada en Edge que almacena el sufijo de la ruta de acceso de la solicitud. Si la ruta base de la solicitud entrante es /animals y la solicitud es /animals/cat, el sufijo de la ruta de acceso es la string literal "/cat".

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

Pregunta: ¿Qué sufijo de ruta del proxy hará que se ejecute SomePolicy? Al igual que con el operador de coincidencias, solo hay una posibilidad en este caso.

Llamada a la API:

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

¿La política se ejecuta? Sí, porque el sufijo de la ruta de acceso del proxy coincide exactamente con “/cat”. No se ejecutará si el sufijo es /bat, /dog, o cualquier otro.

Ahora, creemos una expresión regular con el cuantificador “*”. Este cuantificador coincide con cero o más del carácter anterior.

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

Llamada a la API:

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

¿La política se ejecuta? ¡No! El cuantificador “*” coincide con cero o más del carácter anterior, que es un “c”.

Llamada a la API:

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

¿La política se ejecuta? Sí, porque el comodín coincide con cero o más ocurrencias del carácter anterior.

A continuación, usamos el cuantificador "?", que coincide con el carácter anterior una vez o no coincide en absoluto.

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

Llamada a la API:

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

¿La política se ejecuta? Sí. El cuantificador "?" coincide con cero o una repetición del carácter anterior, que es un "a".

Llamada a la API:

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

¿La política se ejecuta? Sí. El cuantificador "?" coincide con uno o ninguno de los caracteres anteriores. En este caso, no hay un carácter "a", por lo que la condición se evalúa como verdadera.

Llamada a la API:

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

¿La política se ejecuta? No. El cuantificador "?" coincide con uno de los caracteres anteriores, que es un "a".

A continuación, usamos el estilo “[abc]” o “agrupamiento” de la expresión regex. Coincide con los caracteres "a", "b" o "c".

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

Llamada a la API:

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

¿La política se ejecuta? Sí. En este caso, usamos expresiones regulares, y la expresión "[cbr]" coincide con una "c", "b" O "r". Estas llamadas también coinciden:

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

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

Pero esto no es una coincidencia:

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

Pregunta: ¿El operador JavaRegex distingue mayúsculas de minúsculas?

Sí. Supongamos que tienes una condición como la que se muestra a continuación:

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

Llamada a la API:

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

¿La política se ejecuta? Sí, la regex coincide con cero o uno de los caracteres anteriores, que es “a”.

Llamada a la API:

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

Pregunta: ¿La política se ejecuta?

No, porque la "A" mayúscula no coincide con la "a" minúscula.

MatchesPath

El operador MatchesPath también se puede especificar de la siguiente manera: "~/". Se parece un poco a los operadores Matches (~) y JavaRegex (~~). Pero MatchesPath es completamente diferente.

Solo recuerda que este operador considera una ruta de acceso como una serie de partes. Por lo tanto, si la ruta es /animals/cats/wild, se puede considerar que consta de las partes "/animals", "/cats" y "/wild".

El operador MatchesPath te permite usar dos notaciones de comodín: un solo asterisco (*) y un asterisco doble (**). El único asterisco coincide con un elemento de ruta de acceso. El doble asterisco coincide con uno o varios elementos de ruta.

Veamos un ejemplo. En este ejemplo, probamos la variable proxy.pathsuffix, una variable integrada en Edge que almacena el sufijo de la ruta de acceso de la solicitud. Sin embargo, ten en cuenta que puedes probar el valor de cualquier variable de flujo que contenga una string.

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

Pregunta: ¿Qué sufijo de ruta del proxy hará que se ejecute SomePolicy?

Llamada a la API:

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

Pregunta: ¿La política se ejecuta?

No, porque la condición requiere otro elemento de ruta de acceso después de "/animals", según lo especificado en "/*".

Llamada a la API:

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

¿La política se ejecuta? Sí, la ruta de acceso tiene otro elemento de ruta de acceso (la parte después de "/animals/"), pero está vacío.

Llamada a la API:

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

¿La política se ejecuta? Sí, porque la ruta de acceso tiene claramente un elemento ("/cats") que viene después de "/animals"

Llamada a la API:

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

Pregunta: ¿La política se ejecuta?

No, porque el asterisco único solo coincide con un elemento de ruta de acceso, y esta API tiene más de un elemento después de "/animals".

Ahora, usemos el asterisco doble:

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

Pregunta: ¿Qué sufijo de ruta del proxy hará que se ejecute SomePolicy?

Llamada a la API:

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

¿La política se ejecuta? No, porque la condición requiere al menos un elemento de ruta de acceso especificado por "/**".

Llamada a la API:

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

¿La política se ejecuta?

Sí, la ruta de acceso tiene otro elemento de ruta de acceso (la parte después de "/animals/"), pero está vacío.

Llamada a la API:

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

¿La política se ejecuta?

Sí, porque la ruta tiene al menos un elemento después de "/animals"

Llamada a la API:

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

¿La política se ejecuta?

Sí, porque la ruta de acceso tiene más de un elemento que aparece después de "/animals".

Mezcla asteriscos

Puedes usar combinaciones del asterisco simple (*) y doble (**) para definir mejor la coincidencia de rutas.

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

Llamada a la API:

Todas estas llamadas a la API producirán una coincidencia:

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

y

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

y

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

Recursos de la API

Los servicios RESTful son colecciones de recursos de API. Un recurso de API es un fragmento de ruta de URI que identifica algunas entidades a las que los desarrolladores pueden acceder mediante una llamada a tu API. Por ejemplo, si tu servicio proporciona informes y pronósticos del clima, tu servicio de backend podría definir dos recursos de API:

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

Cuando creas un proxy de API (como se muestra en Compila tu primer proxy de API), como mínimo, creas una URL base de alias que se asigna a tu servicio de backend. Por ejemplo:

URL base del backend URL del proxy de API nueva o equivalente
http://mygreatweatherforecast.com http://{your_org}-{environment}.apigee.net/mygreatweatherforecast

En este punto, puedes realizar llamadas a la API de tu backend mediante la URL base. Sin embargo, cuando usas la URL del proxy de API, las cosas ser vuelven interesantes.

Además de las estadísticas de la API que Edge comienza a recopilar cuando usas el proxy de API, los proxies también te permiten definir flujos condicionales que se asignan a los recursos en tu backend. En esencia, “Si entra una llamada GET al recurso /reports, Edge debería realizar una acción”.

En la imagen siguiente, se muestra la diferencia de comportamiento entre dos URL que acceden al mismo backend. Una es la URL del recurso sin proxy y la otra es un proxy de API perimetral con un flujo condicional al mismo recurso de backend. A continuación, describiremos los flujos condicionales con más detalle.

Cómo asignar proxies de API a recursos de backend específicos

Con una URL de proxy de API asignada a la URL base del servicio de backend (cuando creas el proxy), puedes agregar flujos condicionales a recursos específicos, como los recursos /reports y /forecasts que se mencionó anteriormente.

Supongamos que quieres que Edge haga algo cuando llegan las llamadas a los recursos /reports o /forecasts. En este punto, no le indicas a Edge qué hacer, solo que debería detectar llamadas a esos recursos. Esto se hace con las condiciones. En tu proxy de API de Edge, puedes crear flujos condicionales para /reports y /forecasts. Para fines conceptuales, el siguiente XML del proxy de API muestra cómo podrían ser esas condiciones.

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

Esas condiciones indican lo siguiente: "Cuando una solicitud GET se incluya con /reports y /forecasts en la URL, Edge hará lo que tú (el desarrollador de la API) le indiques mediante las políticas que adjuntes a esos flujos.

Este es un ejemplo para indicarle a Edge qué hacer cuando se cumple una condición. En el siguiente XML de proxy de API, cuando se envía una solicitud GET a https://yourorg-test.apigee.net/mygreatweatherforecast/reports, Edge ejecuta la política “XML-to-JSON-1” en la respuesta.

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

Además de esos flujos condicionales, cada proxy de API también incluye dos flujos predeterminados: un <PreFlow> que se ejecuta antes de tus flujos condicionales y un <PostFlow> que se ejecuta después de los flujos condicionales. Esos son útiles para ejecutar políticas cuando se realiza cualquier llamada a un proxy de API. Por ejemplo, si deseas verificar la clave de API de una app con cada llamada, sin importar el recurso de backend al que se accede, puedes colocar una política de verificación de la clave de API en <PreFlow>. Para obtener más información sobre los flujos, consulta Configura flujos.

Crea flujos condicionales a recursos de backend

Definir flujos condicionales en los recursos de backend de un proxy de API es completamente opcional. Sin embargo, esos flujos condicionales te permiten aplicar una administración y supervisión detalladas.

con el que podrás:

  • Aplicar la administración, de manera que refleje la semántica de tu modelo de API
  • Aplicar políticas y comportamiento con secuencias de comandos a rutas de recursos individuales (URI)
  • Recopilar métricas detalladas para los servicios de Analytics

Por ejemplo, imagina que necesitas aplicar diferentes tipos de lógica a tu backend /developers para recursos de /apps.

Para hacerlo, debes agregar dos flujos condicionales en tu proxy de API: /developers y /apps.

En la vista de desarrollo del panel de navegación del editor de proxy de API, haz clic en el ícono + junto a la configuración predeterminada en los extremos del proxy.

En la ventana "Nuevo flujo condicional", debes ingresar los siguientes parámetros de configuración clave:

  • Nombre del flujo: desarrolladores
  • Tipo de condición: Ruta de acceso
  • Ruta de acceso: /developers

La condición se activará (y se ejecutarán las políticas) si se envía una llamada al proxy con /developers al final del URI.

Ahora, agrega un flujo condicional para /apps y imagina que quieres que la condición se active tanto en el URI como en el verbo POST de una solicitud. Debes aplicar la siguiente configuración:

  • Nombre del flujo: Apps
  • Condition Type: Path and Verb
  • Ruta de acceso: /apps
  • Verbo: POST

La condición se activará (y se ejecutarán las políticas) si se envía una llamada al proxy con /apps al final del URI y un verbo POST.

En el panel del navegador, verás nuevos flujos para Apps y Developers.

Selecciona uno de los flujos para ver la configuración de flujo condicional en la vista de código del editor de 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 puedes ver, los recursos de API son simplemente flujos condicionales que evalúan la ruta de URI de la solicitud entrante. (La variable proxy.pathsuffix identifica el URI de la solicitud que sigue a BasePath en la configuración de ProxyEndpoint).

Cada recurso de API que defines se implementa mediante un flujo condicional en el proxy de API. (Consulta Configura flujos).

Una vez que implementes el proxy de API en el entorno de prueba, ocurrirá lo siguiente con esta solicitud:

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

hará que la condición se evalúe como verdadera, y se ejecutará este flujo, junto con las políticas asociadas.

En la siguiente condición de ejemplo, se usa una expresión regular de Java para reconocer las llamadas realizadas al recurso /apps con o sin una barra diagonal final (/apps o /apps/**):

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

Para obtener más información sobre este tipo de condición, consulta Cómo hacer coincidir sin importar ... en la Comunidad de Apigee.

Modela URI jerárquicos

En algunos casos, tendrás recursos de API jerárquicos. Por ejemplo, la API de servicios para desarrolladores proporciona un método para crear una lista de todas las apps que pertenecen a un desarrollador. Esta es la ruta del URI:

/developers/{developer_email}/apps

Es posible que tengas recursos en los que se genere un ID único para cada entidad de una colección, lo que a veces se anota de la siguiente manera:

/genus/:id/species

Esta ruta se aplica de la misma manera a los siguientes dos URI:

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

Para representar esta estructura en un recurso de API, puedes usar comodines. Por ejemplo:

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

resolverá estos URI jerárquicos como recursos de API de forma adecuada.

En algunos casos, en especial para las API muy jerárquicas, es posible que desees resolver todo debajo de un fragmento de URI determinado. Para hacerlo, usa un comodín de asterisco doble en la definición del recurso. Por ejemplo, si defines el siguiente recurso de API:
/developers/**

Ese recurso de API resolverá las siguientes rutas de URI:

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

Así se vería la condición del flujo condicional en la definición del proxy de API:

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

Más ejemplos

Condición adjunta 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>

Condición adjunta a una 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>

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

Ejemplos de operadores en condiciones

Estos son algunos ejemplos de operadores que se usan para crear condiciones:

  • 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 ejemplo práctico: Ignora “/” al final de una ruta de acceso.

Por lo general, los desarrolladores perimetrales desean manejar estos dos sufijos de ruta de acceso: "/cat" y "/cat/". Esto se debe a que algunos usuarios o clientes pueden llamar a tu API con la barra adicional al final de la ruta, y debes poder controlarlo en tus declaraciones condicionales. Este caso práctico exacto se analizó en la comunidad de Apigee.

Si lo prefieres, puedes lograrlo sin usar Regex, de la siguiente manera:

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

Esta es una buena opción. Es claro y legible.

Sin embargo, puedes hacer lo mismo con Regex como este. Los paréntesis se usan para agrupar la parte de regex de la declaración, pero no son obligatorios.

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

Llamadas a la API:

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

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

¿La política se ejecuta? Sí. Ten en cuenta que, en una expresión regular, el carácter "?" significa que debe coincidir con cero o uno de los caracteres anteriores. Por lo tanto, tanto "/cat" como "/cat/" son coincidencias.

Llamada a la API:

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

¿La política se ejecuta? No. La expresión regular coincide con cero o una ocurrencia del carácter anterior y no se permite nada más.

Haz coincidir strings arbitrarias con JavaRegex

En todos los ejemplos de este tema, se muestra cómo hacer coincidir una de las variables de flujo integradas: proxy.pathsuffix. Es bueno saber que puedes realizar coincidencias de patrones en cualquier string arbitraria o variable de flujo, sin importar si se trata de una variable de flujo integrada o no, como proxy.pathsuffix.

Por ejemplo, si tienes una condición que prueba una string arbitraria, tal vez una string que se muestra en una carga útil de backend, o una string que se muestra en una búsqueda del servidor de autenticación, puedes usar operadores coincidentes para probarla. Si usas JavaRegex, la expresión regular se comparará con toda la string de asunto. Si el sujeto es "abc" y la expresión regular es "[a-z]", no hay coincidencia porque "[a-z]" coincide exactamente con un carácter alfa. La expresión "[a-z]+" funciona, al igual que "[a-z]*" y "[a-z]{3}.

Revisemos un ejemplo concreto. Supongamos que el servidor de autenticación muestra una lista de funciones como una string eliminada por comas: "editor, autor, invitado".

Para probar la presencia del rol de editor, esta construcción no funcionará porque “editor” es solo una parte de la string completa.

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

Sin embargo, esta construcción funcionará:

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

Funciona porque tiene en cuenta las divisiones de palabras y cualquier otra parte de la string con el prefijo y el sufijo .*.

En este ejemplo, también puedes probar "editor" con el operador de coincidencias:

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

Sin embargo, JavaRegex suele ser una mejor opción si necesitas más precisión.

Escapa comillas dobles en las expresiones de JavaRegex

La sintaxis de la condición requiere que una expresión JavaRegex esté entre comillas dobles. Por lo tanto, si tienes una expresión Regex que incluye comillas dobles, necesitas una forma alternativa de buscar coincidencias. La respuesta es Unicode. Por ejemplo, supongamos que pasas un encabezado que incluye comillas dobles, como se muestra a continuación:
 -H 'content-type:multipart/related; type="application/xop+xml"'
Si intentas hacer coincidir ese encabezado en una condición Regex, obtendrás un error Condición no válida porque la expresión incluye las comillas dobles:
request.header.Content-Type ~~ "(multipart\/related)(; *type="application\/xop\+xml\")"
La solución es reemplazar las comillas dobles basadas en ASCII con su equivalente Unicode, \u0022. Por ejemplo, la siguiente expresión es válida y produce el resultado esperado:
request.header.Content-Type ~~ "(multipart\/related)(; *type=\u0022application\/xop\+xml\u0022)"