Antimodèle : accéder de façon incorrecte aux en-têtes HTTP à valeurs multiples dans un proxy d'API

<ph type="x-smartling-placeholder"></ph> Vous consultez la documentation Apigee Edge.
Accédez à la page Documentation sur Apigee X.
En savoir plus

Les en-têtes HTTP sont des paires nom/valeur qui permettent aux applications clientes et aux services de backend de transmettre respectivement des informations supplémentaires sur les requêtes et les réponses. Voici quelques exemples simples :

  • L'en-tête d'une requête d'autorisation transmet les identifiants utilisateur au serveur :
    Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
  • L'en-tête Content-Type indique le type de contenu de la requête/réponse envoyée :
    Content-Type: application/json

Les en-têtes HTTP peuvent être associés à une ou plusieurs valeurs en fonction des définitions des champs d'en-tête. Un en-tête à valeurs multiples contient des valeurs séparées par une virgule. Voici quelques exemples d'en-têtes incluant plusieurs valeurs :

  • 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 permet aux développeurs d'accéder facilement aux en-têtes variables de flux dans n'importe quelle règle Edge ou flux conditionnel. Voici la liste des variables que vous pouvez utiliser pour accéder à un en-tête de demande ou de réponse spécifique dans Edge:

Variables de flux :

  • 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

Objets JavaScript :

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

Voici un exemple de règle AssignMessage indiquant comment lire la valeur d'un en-tête de requête et la stocker dans une variable :

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

Antimodèle

Accéder aux valeurs des en-têtes HTTP dans les règles Edge d'une manière qui ne renvoie que la première valeur est incorrecte et peut entraîner des problèmes si un ou plusieurs en-têtes HTTP spécifiques comportent plusieurs valeurs.

Les sections suivantes présentent des exemples d'accès aux en-têtes.

Exemple 1 : Lire un en-tête Accept à valeurs multiples à l'aide du code JavaScript

Notez que l'en-tête Accept contient plusieurs valeurs, comme indiqué ci-dessous :

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

Voici le code JavaScript permettant de lire la valeur de l'en-tête Accept :

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

Le code JavaScript ci-dessus ne renvoie que la première valeur de l'en-tête Accept (par exemple, text/html).

Exemple 2 : Lire un en-tête Access-Control-Allow-Headers à valeurs multiples dans une règle AssignMessage ou RaiseFault

Notez que l'en-tête Access-Control-Allow-Headers contient plusieurs valeurs, comme indiqué ci-dessous :

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

La partie du code de la règle AssignMessage ou RaiseFault permettant de définir l'en-tête Access-Control-Allow-Headers est présentée ci-dessous :

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

Le code ci-dessus ne définit l'en-tête Access-Control-Allow-Headers qu'avec la première valeur de l'en-tête de requête Access-Control-Allow-Headers, content-type dans cet exemple.

Impact

  1. Dans les deux exemples ci-dessus, notez que seule la première valeur des en-têtes à valeurs multiples est renvoyée. Si ces valeurs sont ensuite utilisées par une autre règle du flux de proxy d'API ou par le service de backend pour appliquer une fonction ou une logique, cela peut entraîner un résultat inattendu.
  2. Lorsque les valeurs des en-têtes de requête sont accessibles et transmises au serveur cible, les requêtes API peuvent être traitées par le backend de manière inappropriée et générer des résultats incorrects.
  3. Si l'application cliente dépend de valeurs d'en-tête spécifiques de la réponse Edge, elle peut également être mal traité et donner des résultats incorrects.

Bonne pratique

  1. Utilisez les variables de flux intégrées appropriées : request.header.header_name.values.count, request.header.header_name.N, response.header.header_name.values.count et response.header.header_name.N.

    Effectuez ensuite une itération pour extraire toutes les valeurs d'un en-tête spécifique dans les règles d'appel JavaScript ou Java.

    Exemple : Exemple de code JavaScript permettant de lire un en-tête à valeurs multiples

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

    Par exemple, application/xml;q=0.9, */*;q=0.8 est traité comme une seule valeur dans le code ci-dessus.

    Si les valeurs d'en-tête doivent être fractionnées en utilisant un point-virgule comme délimiteur, utilisez string.split(";") pour les scinder.

  2. Utilisez la fonction substring() dans la variable de flux request.header.header_name.values de la règle RaiseFault ou AssignMessage pour lire toutes les valeurs d'un en-tête spécifique.

    Exemple : Exemple de règle RaiseFault ou AssignMessage permettant de lire un en-tête à valeurs multiples

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

Documentation complémentaire