Ajout de la compatibilité du CORS à un proxy d'API

Cette page s'applique à Apigee et à Apigee hybrid.

Consultez la documentation d'Apigee Edge.

CORS (Cross-Origin Resource Sharing) est un mécanisme standard qui permet aux appels XMLHttpRequest (XHR) exécutés sur une page Web d'interagir avec des ressources extérieures au domaine d'origine. CORS est une solution couramment mise en œuvre à la règle de même origine appliquée par tous les navigateurs. Par exemple, si vous effectuez un appel XHR à l'API Twitter à partir de code JavaScript exécuté dans votre navigateur, l'appel échoue. En effet, le domaine qui diffuse la page vers votre navigateur est différent du domaine diffusant l'API Twitter. CORS offre une solution à ce problème en autorisant des serveurs à accepter explicitement le partage de ressources entre origines multiples.

Cas d'utilisation type pour le CORS

Le code JQuery suivant appelle un service cible fictif. S'il est exécuté depuis le contexte d'un navigateur (une page Web), l'appel échoue en raison de la règle de même origine :

<script>
var url = "http://service.example.com";
$(document).ready(function(){
  $("button").click(function(){
    $.ajax({
        type:"GET",
        url:url,
        async:true,
        dataType: "json",
           success: function(json) {
              // Parse the response.
              // Do other things.
           },
           error: function(xhr, status, err) {
              // This is where we end up!
            }
    });
  });
});
</script>

Une solution à ce problème consiste à créer un proxy d'API Apigee qui appelle l'API de service sur le backend. Gardez en mémoire qu'Apigee se trouve entre le client (dans le cas présent, un navigateur) et l'API backend (le service). Étant donné que le proxy d'API s'exécute sur le serveur, et non dans le navigateur, il est en mesure d'appeler le service. Ensuite, il vous suffit de joindre des en-têtes CORS à la réponse TargetEndpoint. Tant que le navigateur est compatible avec le CORS, ces en-têtes indiquent au navigateur qu'il est possible d'assouplir sa règle de même origine afin de permettre aux appels d'API d'origine différente d'aboutir.

Une fois le proxy compatible avec le CORS créé, vous pouvez appeler l'URL du proxy d'API au lieu du service de backend dans votre code côté client. Exemple :

<script>
var url = "http://myorg-test.apigee.net/v1/example";
$(document).ready(function(){
  $("button").click(function(){
    $.ajax({
        type:"GET",
        url:url,
        async:true,
        dataType: "json",
           success: function(json) {
              // Parse the response.
              // Do other things.
           },
           error: function(xhr, status, err) {
              // This time, we do not end up here!
            }
    });
  });
});
</script>

Associer la règle CORS au PreFlow de requête du ProxyEndpoint

Attribuer une stratégie d'ajout de CORS à un nouveau proxy d'API

Vous pouvez ajouter la compatibilité CORS à un proxy d'API en associant une règle CORS au proxy d'API comme suit :

  • Lorsque vous créez la règle, cochez la case Add CORS header (Ajouter des en-têtes CORS) sur la page Security (Sécurité) de l'assistant Build a Proxy (Créer un proxy).
  • Ajoutez-la ultérieurement à partir de la boîte de dialogue Ajouter une règle.

Lorsque vous ajoutez la règle CORS en cochant la case correspondante, une règle appelée Add CORS (Ajouter le CORS) est automatiquement ajoutée au système et associée au PreFlow de requête TargetEndpoint.

La règle Add CORS (Ajouter le CORS) ajoute les en-têtes appropriés à la réponse. En réalité, ces en-têtes indiquent au navigateur les origines avec lesquelles il partage ses ressources, les méthodes qu'il accepte, etc. Pour en savoir plus sur ces en-têtes CORS, consultez les recommandations W3C Cross-Origin Resource Sharing.

Vous devez modifier la stratégie, comme suit :

  • Ajoutez les en-têtes content-type et authorization (nécessaires pour l'authentification de base ou OAuth2) à l'en-tête Access-Control-Allow-Headers, comme indiqué dans l'extrait de code ci-dessous.
  • Pour l'authentification OAuth2, vous devrez peut-être prendre des mesures pour corriger le comportement non conforme au document RFC.
<CORS continueOnError="false" enabled="true" name="add-cors">
    <DisplayName>Add CORS</DisplayName>
    <AllowOrigins>{request.header.origin}</AllowOrigins>
    <AllowMethods>GET, PUT, POST, DELETE</AllowMethods>
    <AllowHeaders>origin, x-requested-with, accept, content-type, authorization</AllowHeaders>
    <ExposeHeaders>*</ExposeHeaders>
    <MaxAge>3628800</MaxAge>
    <AllowCredentials>false</AllowCredentials>
    <GeneratePreflightResponse>true</GeneratePreflightResponse>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</CORS>

Ajouter des en-têtes CORS à un proxy existant

Nouvel éditeur de proxys

Pour ajouter la règle CORS à un proxy d'API existant, procédez comme suit :

  1. Si vous utilisez l'interface utilisateur d'Apigee dans la console Cloud : sélectionnez Développement de proxys > Proxys d'API.

    Si vous utilisez la version classique de l'interface utilisateur d'Apigee : sélectionnez Développer > Proxys d'API, puis dans le volet Proxys, sélectionnez l'environnement du proxy.

  2. Sélectionnez le proxy d'API auquel vous souhaitez ajouter la règle CORS.
  3. Dans l'éditeur du nouveau proxy d'API, cliquez sur l'onglet Develop (Développer) :
  4. Dans le volet de gauche, cliquez sur le bouton + de la ligne Règles.
  5. Dans la boîte de dialogue Create policy (Créer une règle), cliquez dans le champ Select policy type (Sélectionner un type de règle) et faites défiler la page jusqu'à Security (Security), puis sélectionnez CORS.

  6. Saisissez les détails de la règle, puis cliquez sur Create (Créer).

  7. Dans le volet de navigation de gauche, cliquez sur PreFlow sous Points de terminaison cibles > défaut.
  8. Sélectionnez Proxy Endpoints > default > PreFlow (Points de terminaison du proxy > Par défaut > PreFlow) dans le volet de gauche :

    Points de terminaison cibles pour la sélection du PreFlow dans l'explorateur de proxys

  9. Cliquez sur le bouton + à côté de PreFlow dans le volet Réponse en bas à droite de l'éditeur visuel :

    Cliquez sur le bouton + à côté de "PreFlow" dans le volet "Response"

  10. Dans la boîte de dialogue Add policy step (Ajouter une étape de règle), sélectionnez la règle CORS.
  11. Cliquez sur Add (Ajouter) pour associer la règle.

Éditeur de proxy classique

Pour ajouter la règle CORS à un proxy d'API existant, procédez comme suit :

  1. Connectez-vous à l'UI Apigee.
  2. Sélectionnez Développer > Proxys API dans la barre de navigation de gauche.
  3. Si le bouton Try now (Essayer) s'affiche, cliquez dessus pour afficher la nouvelle vue Develop (Développer).

    La vue Développer est présentée ci-dessous.

    Vue "Develop" dans l'éditeur de proxys

  4. Sélectionnez le proxy d'API auquel vous souhaitez ajouter la règle CORS.
  5. Dans l'éditeur du nouveau proxy d'API, cliquez sur l'onglet Développer :
  6. Dans le volet de navigation de gauche, cliquez sur PreFlow sous Points de terminaison cibles > défaut.
  7. Cliquez sur le bouton +Step supérieur, correspondant au PreFlow de requêtes. Une liste classée de toutes les règles que vous pouvez créer s'affiche.
  8. Sélectionnez CORS dans la catégorie Sécurité.
  9. Saisissez un nom tel que Add CORS, puis cliquez sur Ajouter.

Gérer les requêtes CORS de vérification préliminaire

La vérification préliminaire CORS consiste à envoyer une requête à un serveur pour vérifier s'il est compatible avec CORS. Les réponses de vérification préliminaire types incluent les origines à partir desquelles le serveur acceptera les requêtes CORS, une liste de méthodes HTTP compatibles avec les requêtes CORS, les en-têtes pouvant être utilisés dans le cadre de la requête de ressource, la durée maximale de la réponse de vérification préliminaire qui sera mise en cache, etc. Si le service n'indique pas la compatibilité CORS ou ne souhaite pas accepter les requêtes à origines multiples provenant de l'origine du client, la stratégie à origines multiples du navigateur est appliquée et toute requête interdomaine effectuée à partir du client pour interagir avec des ressources hébergées sur ce serveur échouera.

En règle générale, les requêtes CORS de vérification préliminaire sont effectuées avec la méthode HTTP OPTIONS. Lorsqu'un serveur compatible avec CORS reçoit une requête OPTIONS, il renvoie au client un ensemble d'en-têtes CORS indiquant son niveau de compatibilité CORS. Grâce à ce handshake, le client sait ce qu'il est autorisé à demander à partir du domaine d'origine extérieure.

Pour en savoir plus sur la vérification préliminaire, consultez la page Recommandation W3C Cross-Origin Resource Sharing. Vous y trouverez de nombreux articles et blogs sur le CORS.

Apigee n'inclut pas de solution de vérification CORS préliminaire prête à l'emploi, mais il est possible de mettre en œuvre une telle solution, comme décrit dans cette section. L'objectif est que le proxy puisse évaluer une requête OPTIONS dans un flux conditionnel. Le proxy peut alors renvoyer au client une réponse appropriée.

Examinons un exemple de flux, puis examinons les éléments qui traitent la requête de vérification préliminaire :

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ProxyEndpoint name="default">
    <Description/>
    <Flows>
        <Flow name="OptionsPreFlight">
            <Request>
                <Step>
                    <Name>add-cors</Name>
                </Step>
            </Request>
            <Response/>
        <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition>
        </Flow>
    </Flows>

    <PreFlow name="PreFlow">
        <Request/>
        <Response/>

    </PreFlow>
    <HTTPProxyConnection>
        <BasePath>/v1/cnc</BasePath>
        <VirtualHost>default</VirtualHost>
        <VirtualHost>secure</VirtualHost>
    </HTTPProxyConnection>
    <RouteRule name="NoRoute">
        <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition>
    </RouteRule>
    <RouteRule name="default">
        <TargetEndpoint>default</TargetEndpoint>
   </RouteRule>
   <PostFlow name="PostFlow">
        <Request/>
        <Response/>
    </PostFlow>
</ProxyEndpoint>

Les parties clés de ce ProxyEndpoint sont les suivantes :

  • Une règle RouteRule est créée sur une cible NULL avec une condition pour la requête OPTIONS. Notez qu'aucun TargetEndpoint n'est spécifié. Si une requête OPTIONS est reçue et que les en-têtes de requête Origin et Access-Control-Request-Method sont non nuls, le proxy renvoie immédiatement les en-têtes CORS dans une réponse au client (en contournant la cible "backend" par défaut actuelle). Pour en savoir plus sur les conditions de flux et la règle RouteRule, consultez la section Conditions avec variables de flux.
    <RouteRule name="NoRoute">
        <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition>
    </RouteRule>
    
  • Un flux OptionsPreFlight ajoute au flux une stratégie d'ajout de CORS qui contient les en-têtes CORS si une requête OPTIONS est reçue et si les en-têtes de requête Origin et Access-Control-Request-Method ne sont pas nuls.
     <Flow name="OptionsPreFlight">
                <Request>
                    <Step>
                        <Name>add-cors</Name>
                    </Step>
                </Request>
                <Response/>
            <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition>
     </Flow>