API proxy'sine CORS desteği ekleme

Apigee Edge belgelerini görüntülüyorsunuz.
Apigee X belgelerine gidin.
bilgi

CORS (kaynaklar arası kaynak paylaşımı), bir web sayfasında yürütülen JavaScript XMLHttpRequest (XHR) çağrılarının kaynak olmayan alanlardaki kaynaklarla etkileşim kurmasına olanak tanıyan standart bir mekanizmadır. CORS, tüm tarayıcılar tarafından zorunlu kılınan "aynı kaynak politikası" için yaygın olarak uygulanan bir çözümdür. Örneğin, tarayıcınızda çalıştırılan JavaScript kodundan Twitter API'ye bir XHR çağrısı yaparsanız çağrı başarısız olur. Bunun nedeni, sayfayı tarayıcınıza sunan alan adının Twitter API'sini sunan alan adıyla aynı olmamasıdır. CORS, kaynaklar arası kaynak paylaşımı sağlamak isteyen sunucuların "kaydolmasına" izin vererek bu soruna bir çözüm sunar.

Video: API proxy'sinde CORS'yi nasıl etkinleştireceğinizi öğrenmek için kısa bir video izleyin.

CORS için tipik kullanım alanı

Aşağıdaki JQuery kodu kurgusal bir hedef hizmeti çağırır. Bir tarayıcı (web sayfası) bağlamından yürütülürse çağrı, aynı kaynak politikası nedeniyle başarısız olur:

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

Bu sorunun çözümlerinden biri, arka uçta hizmet API'sini çağıran bir Apigee API proxy'si oluşturmaktır. Edge'in istemci (bu örnekte tarayıcı) ve arka uç API'si (hizmet) arasında bulunduğunu unutmayın. API proxy'si tarayıcıda değil, sunucuda çalıştığı için hizmeti başarılı bir şekilde çözebilir. Ardından, tek yapmanız gereken CORS başlıklarını TargetEndpoint yanıtına eklemektir. Tarayıcı CORS'u desteklediği sürece bu üst bilgiler, tarayıcıya aynı kaynak politikasını "gevşetebileceğini" ve böylece merkezler arası API çağrısının başarılı olmasını sağlayabileceğini belirtir.

CORS destekli proxy oluşturulduktan sonra, istemci tarafı kodunuzda arka uç hizmeti yerine API proxy URL'sini çağırabilirsiniz. Örneğin:

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

Yeni API proxy'sine CORS ekleme politikası ekleme

API proxy'sini oluştururken API proxy'sine "CORS ekle" politikası ekleyerek CORS desteğini API proxy'sine ekleyebilirsiniz. Bu politikayı eklemek için Proxy Oluştur sihirbazının Güvenlik sayfasında CORS başlıkları ekle onay kutusunu seçin.

Bu onay kutusunu işaretlediğinizde CORS ekle adlı bir politika sisteme otomatik olarak eklenir ve aşağıdaki şekilde gösterildiği gibi TargetEndpoint yanıtı ön akışına eklenir:

CORS politikası ekleme politikası, Politikalar bölümündeki gezgine eklendi ve sağ taraftaki bölmede TargetEndpoint yanıtı ön akışına eklendi

CORS ekleme politikası, uygun üstbilgileri yanıta ekleyen bir assignMessage politikası olarak uygulanır. Temel olarak üst bilgiler, tarayıcının kaynaklarını hangi kaynaklarla paylaşacağını, hangi yöntemleri kabul ettiğini ve benzeri bilgileri bilmesini sağlar. Bu CORS başlıkları hakkında daha fazla bilgiyi Kaynaklar Arası Kaynak Paylaşımı W3C Önerisi bölümünde bulabilirsiniz.

Politikayı aşağıdaki şekilde değiştirmeniz gerekir:

  • content-type ve authorization üstbilgilerini (temel kimlik doğrulamasını veya OAuth2'yi desteklemek için gereklidir) aşağıdaki kod alıntısında gösterildiği gibi Access-Control-Allow-Headers üstbilgisine ekleyin.
  • OAuth2 kimlik doğrulaması için, RFC ile uyumlu olmayan davranışı düzeltmeye yönelik adımlar atmanız gerekebilir.
  • CORS başlıklarını ayarlamak için aşağıdaki alıntıda gösterildiği gibi <Add> yerine <Set> kullanmanız önerilir. <Add> kullanırken Access-Control-Allow-Origin üstbilgisi zaten varsa şu hatayı alırsınız:

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

    Daha fazla bilgi için CORS Hatası : Başlık birden çok "*, *" değeri içeriyor ancak yalnızca birine izin veriliyor bölümünü inceleyin.

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

Mevcut bir proxy'ye CORS başlıkları ekleme

Manuel olarak yeni bir Mesaj Atayın politikası oluşturmanız ve önceki bölümde listelenen CORS Ekle politikasının kodunu bu politikaya kopyalamanız gerekir. Ardından politikayı API proxy'sinin TargetEndpoint'in yanıt ön akışına ekleyin. Üstbilgi değerlerini gereken şekilde değiştirebilirsiniz. Politika oluşturma ve ekleme hakkında daha fazla bilgi için Politika nedir? bölümüne bakın.

CORS ön kontrol isteklerini işleme

CORS ön kontrolü, CORS'yi destekleyip desteklemediğini doğrulamak için bir sunucuya istek göndermeyi ifade eder. Genel ön kontrol yanıtları arasında sunucunun hangi kaynaklardan CORS isteklerini kabul edeceği, CORS istekleri için desteklenen HTTP yöntemlerinin listesi, kaynak isteğinin bir parçası olarak kullanılabilen başlıklar, ön kontrol yanıtının önbelleğe alınacağı maksimum süre vb. bulunur. Hizmet, CORS desteğini belirtmiyorsa veya istemcinin kaynağından gelen kaynaklar arası istekleri kabul etmek istemiyorsa tarayıcının kaynaklar arası politikası uygulanır ve ilgili sunucuda barındırılan kaynaklarla etkileşim kurmak için istemciden alan adları arası yapılan tüm istekler başarısız olur.

Genellikle CORS ön kontrol istekleri HTTP OPTIONS yöntemiyle yapılır. CORS'u destekleyen bir sunucu OPTIONS isteği aldığında, istemciye CORS destek düzeyini belirten bir dizi CORS başlığı döndürür. Bu el sıkışmanın sonucunda istemci, kaynak olmayan alandan neler isteyebileceğini bilir.

Ön kontrol hakkında daha fazla bilgi için Kaynaklar Arası Kaynak Paylaşımı W3C Önerisi'ne bakın. Ayrıca CORS ile ilgili başvurabileceğiniz çok sayıda blog ve makale de bulunmaktadır.

Apigee, kullanıma hazır bir CORS ön kontrol çözümü içermese de bu bölümde açıklandığı gibi uygulanması mümkündür. Amaç, proxy'nin koşullu akışta bir OPTIONS isteğini değerlendirmesidir. Ardından proxy, istemciye uygun bir yanıt gönderebilir.

Şimdi örnek bir akışa bakalım ve ardından yayın öncesi isteğini işleyen bölümleri tartışalım:

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

Bu ProxyEndpoint'in önemli kısımları aşağıda belirtilmiştir:

  • OPTIONS isteği için bir koşul içeren NULL hedefe yönelik bir RouteRule oluşturulur. TargetEndpoint belirtilmediğini unutmayın. OPTIONS isteği alınırsa ve Origin ve Access-Control-Request-Method istek başlıkları boş değilse proxy, istemciye yanıt olarak hemen CORS üst bilgilerini döndürür (gerçek varsayılan "arka uç" hedefini atlar). Akış koşulları ve RouteRule ile ilgili ayrıntılar için Akış değişkenleri içeren koşullar bölümüne bakın.

    <RouteRule name="NoRoute">
        <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition>
    </RouteRule>
    
  • Bir OPTIONS isteği alındığında ve Kaynak ve Access-Control-Request-Method istek başlıkları boş değilse akışa CORS başlıklarını içeren CORS ekle politikası ekleyen bir OptionsPreFlight akışı oluşturulur.

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

Örnek CORS çözümünü kullanma

GitHub'da, paylaşılan akış olarak uygulanmış örnek bir CORS çözümü mevcuttur. Paylaşılan akış paketini ortamınıza aktarın ve akış kancalarını kullanarak ya da doğrudan API proxy akışlarına ekleyin. Ayrıntılar için örnekle birlikte sağlanan CORS-Shared-FLow README dosyasını inceleyin.