Menambahkan dukungan CORS ke proxy API

Anda sedang melihat dokumentasi Apigee Edge.
Buka Dokumentasi Apigee X.
info

CORS (Cross-origin resource sharing) adalah mekanisme standar yang memungkinkan JavaScript Panggilan XMLHttpRequest (XHR) yang dijalankan di halaman web untuk berinteraksi dengan resource dari non-asal domain. CORS adalah solusi yang umum diterapkan untuk "kebijakan origin yang sama" yang diberlakukan oleh semua browser. Misalnya, jika Anda membuat panggilan XHR ke Twitter API dari kode JavaScript mengeksekusi di browser Anda, panggilan akan gagal. Hal ini karena domain menyalurkan laman untuk browser Anda tidak sama dengan domain yang menyajikan Twitter API. CORS memberikan solusi untuk masalah ini dengan mengizinkan server untuk memilih ikut serta jika mereka ingin menyediakan resource lintas origin berbagi.

Video: Tonton video singkat untuk mempelajari cara mengaktifkan CORS pada proxy API.

Kasus penggunaan umum untuk CORS

Kode JQuery berikut memanggil layanan target fiktif. Jika dieksekusi dari dalam konteks browser (halaman web), panggilan akan gagal karena kebijakan origin yang sama:

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

Salah satu solusi untuk masalah ini adalah dengan membuat proxy API Apigee yang memanggil API layanan backend. Perlu diingat bahwa Edge berada di antara klien (dalam hal ini browser) dan backend API (layanan). Karena {i>proxy<i} API dieksekusi di server, bukan di browser, {i>proxy<i} dapat memanggil layanan. Lalu, yang perlu Anda lakukan melampirkan header CORS ke respons TargetEndpoint. Selama browser mendukung CORS, {i>header<i} ini memberi sinyal ke {i>browser<i} bahwa Anda dapat "rileks" kebijakan dari origin yang sama, panggilan API lintas origin agar berhasil.

Setelah proxy dengan dukungan CORS dibuat, Anda dapat memanggil URL proxy API, bukan layanan backend di kode sisi klien Anda. Contoh:

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

Melampirkan kebijakan Tambahkan CORS ke API baru {i>proxy<i}

Anda dapat menambahkan dukungan CORS ke proxy API dengan melampirkan "Tambahkan CORS" kebijakan ke proxy API saat Anda membuatnya. Untuk menambahkan kebijakan ini, centang kotak Add CORS headers di halaman Security pada wizard {i> Build a Proxy<i}.

Jika Anda mencentang kotak ini, kebijakan yang disebut Tambahkan CORS akan otomatis ditambahkan ke sistem dan dilampirkan ke alur awal respons TargetEndpoint, seperti ditunjukkan dalam gambar berikut:

Tambahkan kebijakan CORS yang ditambahkan ke navigator di bagian Kebijakan dan dilampirkan ke preflow respons TargetEndpoint di panel kanan

Kebijakan Tambahkan CORS diimplementasikan sebagai kebijakan MenetapkanMessage, yang menambahkan header yang sesuai ke respons. Pada dasarnya, {i>header<i} memberi tahu {i>browser<i} mana sumber daya yang akan diberi {i>resource<i}, metode apa yang diterima, dan seterusnya. Anda dapat membaca header CORS ini lebih lanjut di Rekomendasi W3C untuk Cross-Origin Resource Sharing.

Anda harus mengubah kebijakan sebagai berikut:

  • Tambahkan header content-type dan authorization (diperlukan untuk mendukung autentikasi dasar atau OAuth2) ke header Access-Control-Allow-Headers, seperti ditunjukkan dalam cuplikan kode di bawah.
  • Untuk autentikasi OAuth2, Anda mungkin perlu mengambil langkah untuk memperbaiki perilaku yang tidak sesuai dengan RFC.
  • Sebaiknya gunakan <Set> untuk menetapkan header CORS, bukan <Add>, seperti yang ditunjukkan dalam cuplikan di bawah. Saat menggunakan <Add>, jika header Access-Control-Allow-Origin sudah ada, Anda akan menerima error berikut:

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

    Untuk informasi selengkapnya, lihat Error CORS : header berisi beberapa nilai '*, *', tetapi hanya satu yang diizinkan.

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

Menambahkan header CORS ke proxy yang ada

Anda harus membuat kebijakan Tetapkan Pesan baru secara manual dan menyalin kode untuk Tambahkan CORS kebijakan yang tercantum di bagian sebelumnya. Kemudian, lampirkan kebijakan tersebut ke alur respons TargetEndpoint dari proxy API. Anda dapat mengubah nilai header sesuai kebutuhan. Untuk selengkapnya informasi tentang cara membuat dan melampirkan kebijakan, lihat Apa yang dimaksud dengan kebijakan?.

Menangani CORS permintaan preflight

Preflight CORS mengacu pada pengiriman permintaan ke server untuk memverifikasi mendukung CORS. Respons preflight umum mencakup origin mana yang akan diterima server CORS daftar metode HTTP yang didukung untuk permintaan CORS, header yang dapat digunakan sebagai bagian dari permintaan resource, waktu maksimum respons preflight akan di-cache, dan lainnya. Jika layanan tidak menunjukkan dukungan CORS atau tidak ingin menyetujui permintaan lintas origin permintaan dari asal klien, kebijakan lintas asal browser akan diterapkan dan semua permintaan lintas domain yang dibuat dari klien untuk berinteraksi dengan sumber daya yang dihosting di server tersebut akan gagal.

Biasanya, permintaan preflight CORS dibuat dengan metode HTTP OPTIONS. Ketika server yang mendukung CORS menerima permintaan OPTIONS, tindakan ini akan menampilkan serangkaian header CORS ke klien yang menunjukkan tingkat dukungan CORS-nya. Sebagai hasil dari {i>handshake <i}ini, klien tahu apa yang diizinkan untuk meminta dari domain non-origin.

Untuk mengetahui informasi selengkapnya tentang preflight, lihat Rekomendasi W3C Cross-Origin Resource Sharing. Terdapat di menambahkan banyak blog dan artikel tentang CORS yang dapat Anda rujuk.

Apigee tidak langsung menyertakan solusi preflight CORS, tetapi mungkin saja terapkan, seperti yang dijelaskan dalam bagian ini. Tujuannya adalah agar proxy mengevaluasi OPTIONS dalam alur bersyarat. Kemudian, {i>proxy<i} dapat mengirim respons yang sesuai kembali ke dengan klien besar.

Mari kita lihat contoh alur, lalu bahas bagian yang menangani permintaan preflight:

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

Bagian penting dari ProxyEndpoint ini adalah sebagai berikut:

  • RouteRule dibuat ke target NULL dengan kondisi untuk permintaan OPTIONS. Perlu diketahui bahwa tidak ada TargetEndpoint yang ditentukan. Jika permintaan OPTIONS diterima dan Asal dan {i>Header<i} permintaan {i>Access-Control-Request-Method<i} tidak null, {i>proxy<i} langsung mengembalikan CORS sebagai respons terhadap klien (dengan mengabaikan target "backend" default sebenarnya). Untuk mengetahui detail kondisi alur dan RouteRule, lihat Kondisi dengan variabel alur.

    <RouteRule name="NoRoute">
        <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition>
    </RouteRule>
    
  • Alur OptionsPreFlight dibuat yang menambahkan kebijakan Tambahkan CORS, yang berisi CORS header, ke flow jika permintaan OPTIONS diterima dan Asal serta Header permintaan Access-Control-Request-Method bukan null.

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

Menggunakan contoh solusi CORS

Contoh solusi CORS, yang diimplementasikan sebagai alur bersama, tersedia di GitHub. Impor paket alur bersama ke lingkungan Anda dan lampirkan menggunakan flow hook atau langsung ke alur proxy API. Untuk mengetahui detailnya, lihat File README CORS-Shared-FLow yang disediakan bersama sampel.