Antipatrón: Accede a encabezados HTTP de valores múltiples de forma incorrecta en un proxy de API

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

Los encabezados HTTP son los pares de nombre y valor que permiten a las aplicaciones cliente y los servicios de backend pasar información adicional sobre las solicitudes y respuestas, respectivamente. A continuación, se muestran algunos ejemplos simples:

  • El encabezado de la solicitud de autorización pasa las credenciales del usuario al servidor:
    Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
  • El encabezado Content-Type indica el tipo de contenido de solicitud o respuesta que se envía:
    Content-Type: application/json

Los encabezados HTTP pueden tener uno o más valores según las definiciones del campo del encabezado. Un encabezado con valores múltiples tendrá valores separados por comas. Estos son algunos ejemplos de encabezados que contienen varios valores:

  • Cache-Control: no-cache, no-store, must-revalidate
  • Accept: text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8
  • X-Forwarded-For: 10.125.5.30, 10.125.9.125

Apigee Edge permite a los desarrolladores acceder a los encabezados fácilmente mediante variables de flujo en cualquiera de las políticas de Edge o flujos condicionales. A continuación, se muestra la lista de variables que se pueden usar para acceder a un encabezado de solicitud o respuesta específico en Edge:

Variables de flujo

  • message.header.header-name
  • request.header.header-name
  • response.header.header-name
  • message.header.header-name.N
  • request.header.header-name.N
  • response.header.header-name.N

Objetos de JavaScript:

  • context.proxyRequest.headers.header-name
  • context.targetRequest.headers.header-name
  • context.proxyResponse.headers.header-name
  • context.targetResponse.headers.header-name

A continuación, se muestra una política de AssignMessage de ejemplo en la que se muestra la forma de leer el valor de un encabezado de solicitud y guardarlo en una variable:

<AssignMessage continueOnError="false" enabled="true" name="assign-message-default">
  <AssignVariable>
    <Name>reqUserAgent</Name>
    <Ref>request.header.User-Agent</Ref>
  </AssignVariable>
</AssignMessage>

Antipatrón

El acceso a los valores de los encabezados HTTP en las políticas Edge de una manera que solo muestra el primer valor es incorrecto y puede causar problemas si los encabezados HTTP específicos tienen más de un valor.

Las siguientes secciones contienen ejemplos de acceso a encabezados.

Ejemplo 1: Lee un encabezado Accept de varios valores mediante el código JavaScript

Ten en cuenta que el encabezado Accept tiene varios valores como se muestra a continuación:

Accept: text/html, application/xhtml+xml, application/xml

Este es el código de JavaScript que lee el valor del encabezado Accept:

// Read the values from Accept header
var acceptHeaderValues = context.getVariable("request.header.Accept");

El código JavaScript anterior muestra solo el primer valor del encabezado Accept, como text/html.

Ejemplo 2: Lee el encabezado de acceso-control-Allow-Headers de varios valores en la política AssignMessage o RaiseFault

Ten en cuenta que el encabezado Access-Control-Allow-Headers tiene varios valores como se muestra a continuación:

Access-Control-Allow-Headers: content-type, authorization

A continuación, se muestra el fragmento de código de la política AssignMessage o RaiseFault mediante el encabezado Access-Control-Allow-Headers:

<Set>
  <Headers>
    <Header name="Access-Control-Allow-Headers">{request.header.Access-Control-Request-Headers}</Header>
  </Headers>
</Set>

Mediante el código anterior, se establece el encabezado Access-Control-Allow-Headers con solo el primer valor del encabezado de la solicitud Access-Control-Allow-Headers, en este ejemplo content-type.

Impacto

  1. En ambos ejemplos anteriores, observa que solo se muestra el primer valor de los encabezados con valores múltiples. Si otra política del flujo del proxy de API o el servicio de backend usan estos valores posteriormente para realizar alguna función o lógica, podría generar un resultado inesperado.
  2. Cuando se accede a los valores del encabezado de solicitud y se pasan al servidor de destino, el backend podría procesar las solicitudes realizadas a la API de manera incorrecta y, por lo tanto, mostrar resultados incorrectos.
  3. Si la aplicación cliente depende de valores de encabezado específicos de la respuesta de Edge, es posible que también se procese de forma incorrecta y muestre resultados incorrectos.

Práctica recomendada

  1. Usa las variables de flujo integradas adecuadas: request.header.header_name.values.count, request.header.header_name.N, response.header.header_name.values.count, response.header.header_name.N.

    Luego, itera para recuperar todos los valores de un encabezado específico en las políticas de texto destacado de JavaScript o Java.

    Ejemplo: Código de JavaScript de muestra para leer un encabezado de varios valores

    for (var i = 1; i <=context.getVariable('request.header.Accept.values.count'); i++)
    {
      print(context.getVariable('request.header.Accept.' + i));
    }
    

    Por ejemplo, application/xml;q=0.9, */*;q=0.8 aparecerá como un valor con el código anterior.

    Si los valores del encabezado deben dividirse con punto y coma como delimitador, usa string.split(";") para separarlos en valores.

  2. Usa la función substring() en la variable de flujo request.header.header_name.values en la política RaiseFault o AssignMessage para leer todos los valores de un encabezado específico.

    Ejemplo: Ejemplo de política de RaiseFault o AssignMessage para leer un encabezado de varios valores

    <Set>
      <Headers>
       <Header name="Access-Control-Allow-Headers">{substring(request.header.Access-Control-Request-Headers.values,1,-1)}</Header>
      </Headers>
    </Set>
    

Lecturas adicionales