Einem API-Proxy CORS-Unterstützung hinzufügen

Sie sehen die Dokumentation zu Apigee Edge.
Zur Apigee X-Dokumentation
weitere Informationen

Mithilfe des Standardmechanismus CORS (Cross-Origin Resource Sharing) können JavaScript XMLHttpRequest-Aufrufe (XHR), die auf einer Webseite ausgeführt werden, mit Ressourcen von Nicht-Origin-Domains interagieren. CORS ist eine häufig implementierte Lösung der „Same-Origin-Richtlinie“, die von allen Browsern durchgesetzt wird. Wenn Sie beispielsweise einen XHR-Aufruf an die Twitter-API von einem im Browser ausgeführten JavaScript-Code aus vornehmen, schlägt der Aufruf fehl. Das liegt daran, dass die Domain, mit der die Seite in Ihrem Browser bereitgestellt wird, nicht dieselbe Domain ist wie die von der Twitter API bereitgestellte. CORS bietet eine Lösung für dieses Problem, denn die Server können per „Opt-in“ zustimmen, wenn sie eine ursprungsübergreifende Ressourcenfreigabe bereitstellen möchten.

Video: Schauen Sie sich ein kurzes Video an, um zu erfahren, wie Sie CORS für einen API-Proxy aktivieren.

Typischer Anwendungsfall für CORS

Der folgende JQuery-Code ruft einen fiktiven Zieldienst auf. Bei Ausführung im Kontext eines Browsers (einer Webseite) schlägt der Aufruf aufgrund der Same-Origin-Richtlinie fehl:

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

Eine Lösung für dieses Problem besteht darin, einen Apigee API-Proxy zu erstellen, der die Service API auf dem Back-End aufruft. Denken Sie daran, dass sich Edge zwischen dem Client (in diesem Fall ein Browser) und der Back-End-API (dem Dienst) befindet. Da der API-Proxy auf dem Server und nicht in einem Browser ausgeführt wird, kann er den Dienst erfolgreich aufrufen. Dann müssen Sie nur noch CORS-Header an die TargetEndpoint-Antwort anhängen. Solange der Browser CORS unterstützt, signalisieren diese Header dem Browser, dass es in Ordnung ist, seine Same-Origin-Richtlinie zu lockern. Dadurch ist der Cross-Origin API-Aufruf erfolgreich.

Sobald der Proxy mit der CORS-Unterstützung erstellt wurde, können Sie die API-Proxy-URL anstelle des Back-End-Dienstes in Ihrem clientseitigen Code aufrufen. Beispiel:

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

„CORS-Richtlinie hinzufügen“ an einen neuen API-Proxy anhängen

Sie können einem API-Proxy die CORS-Unterstützung hinzufügen, indem Sie beim Erstellen der API eine Richtlinie „CORS hinzufügen“ anhängen. Wenn Sie diese Richtlinie hinzufügen möchten, klicken Sie auf der Seite „Sicherheit“ des Assistenten zum Erstellen eines Proxy auf das Kästchen CORS-Header hinzufügen.

Wenn Sie dieses Kästchen anklicken, wird dem System automatisch eine Richtlinie namens CORS hinzufügen hinzugefügt und an die TargetEndpoint-Antwort angehängt. Dies ist in der folgenden Abbildung dargestellt:

CORS-Richtlinie zum Navigator unter &quot;Richtlinien&quot; hinzufügen und mit der Aufhängung der TargetEndpoint-Antwort in der rechten Fensterposition verknüpfen

Die Richtlinie „CORS hinzufügen“ ist als AssignMessage-Richtlinie implementiert, die der Antwort die entsprechenden Header hinzufügt. Im Prinzip teilen die Header dem Browser mit, mit welchen Ursprüngen er seine Ressourcen teilt, welche Methoden er akzeptiert und so weiter. Weitere Informationen zu diesen CORS-Headern finden Sie in der W3C-Empfehlung zum Cross-Origin Resource Sharing.

Sie sollten die Richtlinie wie folgt ändern:

  • Fügen Sie dem Header Access-Control-Allow-Headers die Header content-type und authorization hinzu, wie im folgenden Code-Snippet dargestellt. Dies ist erforderlich, um die Basisauthentifizierung oder OAuth2 zu unterstützen:
  • Für die OAuth2-Authentifizierung müssen Sie gegebenenfalls Maßnahmen ergreifen, um das nicht-RFC-konforme Verhalten zu beheben.
  • Wir empfehlen <Set> statt <Add>, um die CORS-Header festzulegen, wie im folgenden Auszug zu sehen ist. Wenn Sie <Add> verwenden und der Header Access-Control-Allow-Origin bereits vorhanden ist, wird der folgende Fehler angezeigt:

    The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed.

    Weitere Informationen finden Sie unter CORS-Fehler : Header enthält mehrere Werte „*“ und „*“, aber nur einer ist zulässig.

<AssignMessage async="false" continueOnError="false" enabled="true" name="add-cors">
    <DisplayName>Add CORS</DisplayName>
    <FaultRules/>
    <Properties/>
    <Set>
        <Headers>
            <Header name="Access-Control-Allow-Origin">{request.header.origin}</Header>
            <Header name="Access-Control-Allow-Headers">origin, x-requested-with, accept, content-type, authorization</Header>
            <Header name="Access-Control-Max-Age">3628800</Header>
            <Header name="Access-Control-Allow-Methods">GET, PUT, POST, DELETE</Header>
        </Headers>
    </Set>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="response"/>
</AssignMessage>

CORS-Headern zu einem vorhandenen Proxy hinzufügen

Sie müssen manuell eine neue Richtlinie „Nachricht zuweisen“ erstellen und den Code für die im vorherigen Abschnitt aufgeführte Richtlinie „CORS hinzufügen“ kopieren. Hängen Sie dann die Richtlinie an den Antwort-PreFlow des TargetEndpoint des API-Proxys an. Sie können die Header-Werte nach Bedarf ändern. Weitere Informationen zum Erstellen und Anhängen von Richtlinien finden Sie unter Was ist eine Richtlinie?.

CORS-Preflight-Anfragen verarbeiten

CORS Preflight bezieht sich auf das Senden einer Anfrage an einen Server, um zu kontrollieren, ob CORS unterstützt wird. Typische Preflight-Antworten sind z. B., von welchen Quellen der Server CORS-Anfragen akzeptiert, eine Liste von HTTP-Methoden, die für CORS-Anfragen unterstützt werden, Header, die als Teil der Ressourcenanfrage verwendet werden können, die maximale Zeit, für die eine Preflight-Antwort im Cache gespeichert wird und mehr. Wenn der Dienst keine CORS-Unterstützung anzeigt oder keine Cross-Origin-Anfragen vom Ursprung des Kunden annehmen möchte, wird die Cross-Origin-Richtlinie des Browsers erzwungen und alle domainübergreifenden Anfragen vom Client, mit Ressourcen auf diesem Server zu interagieren, werden fehlschlagen.

In der Regel werden CORS-Preflight-Anfragen mit der HTTP-OPTIONEN-Methode gestellt. Wenn ein Server, der CORS unterstützt, eine OPTIONS-Anfrage erhält, gibt er eine Reihe von CORS-Headern an den Client zurück, die die Ebene der CORS-Unterstützung angeben. Aufgrund dieses Handshakes weiß der Client, was er von der Nicht-Ursprungsdomain anfordern darf.

Weitere Informationen zum Preflight finden Sie in der W3C-Empfehlung zum Cross-Origin Resource Sharing. Darüber hinaus gibt es zahlreiche Blogs und Artikel zu CORS, auf die Sie zurückgreifen können.

Apigee enthält von Haus aus keine CORS-Preflight-Lösung, aber es ist möglich, sie zu implementieren, wie in diesem Abschnitt beschrieben. Das Ziel für den Proxy besteht darin, eine OPTIONS-Anfrage in einem bedingten Ablauf auszuwerten. Der Proxy kann dann eine entsprechende Antwort an den Client senden.

Sehen wir uns einen Beispielablauf und dann die Teile an, die die Preflight-Anfrage verarbeiten:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ProxyEndpoint name="default">
    <Description/>
    <Flows>
        <Flow name="OptionsPreFlight">
            <Request/>
            <Response>
                <Step>
                    <Name>add-cors</Name>
                </Step>
            </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>

Dieser ProxyEndpoint besteht aus folgenden Hauptkomponenten:

  • Eine an ein NULL-Ziel gerichtete RouteRule wird mit einer Bedingung für die OPTIONS-Anfrage erstellt. Beachten Sie, dass kein TargetEndpoint angegeben wird. Wenn die OPTIONS-Anfrage empfangen wird und die Anfrageheader „Origin“ und „Access-Control-Request-Method“ nicht NULL sind, gibt der Proxy sofort die CORS-Header in einer Antwort an den Client zurück (unter Umgehung des tatsächlichen Standard-Back-End-Ziels). Weitere Informationen zu Flussbedingungen und RouteRule finden Sie unter Bedingungen mit Flussvariablen.

    <RouteRule name="NoRoute">
        <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition>
    </RouteRule>
    
  • Es wird ein OptionsPreFlight-Ablauf erstellt, der dem Ablauf eine CORS-Richtlinie zum Hinzufügen hinzufügt, die die CORS-Header enthält, wenn eine OPTIONS-Anfrage empfangen wird und die Origin- und Access-Control-Request-Method-Anfrageheader nicht null sind.

     <Flow name="OptionsPreFlight">
                <Request/>
                <Response>
                    <Step>
                        <Name>add-cors</Name>
                    </Step>
                </Response>
            <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition>
     </Flow>
    

CORS-Beispiellösung verwenden

Eine Beispiel-CORS-Lösung, die als freigegebener Ablauf implementiert wird, ist auf GitHub verfügbar. Importieren Sie das freigegebene Ablauf-Bundle in Ihre Umgebung und hängen Sie es mit Ablauf-Hooks oder direkt an die API-Proxy-Abläufe an. Weitere Informationen finden Sie in der mit dem Beispiel bereitgestellten CORS-Shared-FLow-Readme-Datei.