Hal ini memungkinkan browser untuk mengeluarkan permintaan XMLHttpRequest ke server silang-asal, sehingga mengatasi batasan bahwa AJAX hanya dapat digunakan di asal yang sama.
Artikel ini memperkenalkan mekanisme internal COR secara rinci.
(Deskripsi foto: Diambil di Oasis Park di Al Ain, UEA)
1. Pendahuluan
CORS membutuhkan dukungan browser dan server. Saat ini, semua browser mendukung fungsi ini, dan IE browser tidak dapat lebih rendah dari IE10.
Seluruh proses komunikasi CORS secara otomatis diselesaikan oleh browser dan tidak memerlukan partisipasi pengguna. Untuk pengembang, komunikasi CORS tidak berbeda dari komunikasi AJAX asal yang sama, dan kodenya persis sama. Setelah browser menemukan bahwa AJAX meminta silang, itu akan secara otomatis menambahkan beberapa informasi header tambahan, dan kadang-kadang akan ada permintaan tambahan, tetapi pengguna tidak akan merasakannya.
Oleh karena itu, kunci untuk mengimplementasikan komunikasi CORS adalah server. Selama server mengimplementasikan antarmuka CORS, komunikasi lintas asal dapat dilakukan.
Dua permintaan
Browser membagi permintaan CORS menjadi dua kategori: permintaan sederhana dan permintaan tidak terlalu sederhana.
Selama dua kondisi utama berikut dipenuhi pada saat yang sama, ini adalah permintaan sederhana.
(1) Metode permintaan adalah salah satu dari tiga metode berikut:
Headgetpost
(2) Informasi header HTTP tidak melebihi bidang berikut:
Acceptaccept-Languagecontent-Languagelast-event-Idcontent-Type: Hanya terbatas pada tiga nilai application/x-www-form-urlencoded , multipart/form-data , text/plain
Siapa pun yang tidak memenuhi dua kondisi di atas pada saat yang sama adalah permintaan yang tidak sederhana.
Penanganan browser atas kedua permintaan ini berbeda.
3. Permintaan Sederhana 3.1 Proses Dasar
Untuk permintaan sederhana, browser secara langsung mengeluarkan permintaan CORS. Secara khusus, tambahkan bidang Origin ke informasi header.
Berikut ini adalah contoh. Browser menemukan bahwa permintaan AJAX lintas asal ini adalah permintaan sederhana, dan secara otomatis menambahkan bidang Origin ke informasi header.
GET /cors HTTP/1.1Origin: http://api.bob.comHost: api.alice.comAccept-Language: en-USConnection: keep-aliveUser-Agent: Mozilla/5.0...
Dalam informasi header di atas, bidang Origin digunakan untuk menunjukkan sumber mana (protokol + nama domain + port) permintaan berasal. Berdasarkan nilai ini, server memutuskan apakah akan menyetujui permintaan tersebut.
Jika sumber yang ditentukan berdasarkan Origin tidak berada dalam ruang lingkup izin, server akan mengembalikan respons HTTP normal. Browser menemukan bahwa informasi header dari respons ini tidak berisi bidang Access-Control-Allow-Origin (lihat di bawah untuk detailnya), jadi diketahui bahwa kesalahan terjadi, dan dengan demikian kesalahan dilemparkan, yang ditangkap oleh fungsi panggilan balik onerror dari XMLHttpRequest . Perhatikan bahwa kesalahan ini tidak dapat diidentifikasi oleh kode status, karena kode status respons HTTP mungkin 200.
Jika nama domain yang ditentukan oleh Origin berada dalam ruang lingkup izin, respons yang dikembalikan oleh server akan memiliki beberapa bidang header tambahan.
Access-Control-Allow-Origin: http://api.bob.comAccess-Control-Allow-Credentials: trueAccess-Control-Expose-Headers: FooBarContent-Type: text/html; charset=utf-8
Di antara informasi header di atas, ada tiga bidang yang terkait dengan permintaan CORS, semuanya dimulai dengan Access-Control- .
(1) Access-Control-Wallow-Origin
Bidang ini diperlukan. Nilainya adalah nilai bidang Origin pada saat permintaan, atau * , menunjukkan bahwa permintaan untuk nama domain apa pun diterima.
(2) Access-Control-Allow-Credentials
Bidang ini opsional. Nilainya adalah nilai boolean yang menunjukkan apakah akan mengizinkan pengiriman cookie. Secara default, cookie tidak termasuk dalam permintaan CORS. Diatur ke true , yang berarti server secara eksplisit memungkinkannya. Cookie dapat dimasukkan dalam permintaan dan dikirim ke server bersama -sama. Nilai ini hanya dapat diatur ke true . Jika server tidak mengirim cookie oleh browser, hapus bidang.
(3) Access-Control-Expose-Headers
Bidang ini opsional. Saat CORS meminta, metode getResponseHeader() dari objek XMLHttpRequest hanya bisa mendapatkan 6 bidang dasar: Cache-Control , Content-Language , Content-Type , Expires , Last-Modified , Pragma . Jika Anda ingin mendapatkan bidang lain, Anda harus menentukannya di Access-Control-Expose-Headers . Contoh di atas menentukan bahwa getResponseHeader('FooBar') dapat mengembalikan nilai bidang FooBar .
3.2 Atribut Withcredentials
Seperti disebutkan di atas, permintaan CORS tidak mengirim cookie dan informasi otentikasi HTTP secara default. Jika Anda ingin mengirim cookie ke server, di satu sisi, Anda memerlukan server untuk menyetujui dan menentukan bidang Access-Control-Allow-Credentials .
Access-Control-Allow-Credentials: true Di sisi lain, pengembang harus membuka properti withCredentials dalam permintaan AJAX.
var xhr = new XMLHttpRequest();xhr.withCredentials = true;Kalau tidak, browser tidak akan mengirim bahkan jika server setuju untuk mengirim cookie. Atau, server membutuhkan cookie untuk diatur, dan browser tidak akan menanganinya.
Namun, jika pengaturan withCredentials dihilangkan, beberapa browser masih akan mengirim cookie bersama. Pada saat ini, Anda dapat secara eksplisit menutup withCredentials .
xhr.withCredentials = false; Perlu dicatat bahwa jika Anda ingin mengirim cookie, Access-Control-Allow-Origin tidak dapat ditetapkan sebagai tanda bintang, dan Anda harus menentukan nama domain eksplisit yang konsisten dengan halaman web yang diminta. Pada saat yang sama, cookie masih mengikuti kebijakan asal yang sama. Hanya cookie yang disetel dengan nama domain server yang akan diunggah. Cookie dari nama domain lain tidak akan diunggah, dan document.cookie Cookies dalam kode halaman web asli (lintas-orisinal) tidak dapat membaca cookie di bawah nama domain server.
4. Permintaan Non-Simple 4.1 Permintaan Pra-penerbangan
Permintaan non-sederhana adalah permintaan yang memiliki persyaratan khusus untuk server, seperti metode permintaan PUT atau DELETE , atau jenis bidang Content-Type adalah application/json .
Permintaan CORS yang bukan permintaan sederhana akan menambahkan permintaan kueri HTTP sebelum komunikasi resmi, yang disebut permintaan "preflight".
Browser First bertanya kepada server apakah nama domain di mana halaman web saat ini berada di daftar lisensi server, dan kata kerja http dan bidang header yang dapat digunakan. Hanya ketika balasan positif diterima, browser akan mengeluarkan permintaan XMLHttpRequest formal, jika tidak kesalahan akan dilaporkan.
Di bawah ini adalah skrip javascript browser.
var url = 'http://api.alice.com/cors';var xhr = new XMLHttpRequest();xhr.open('PUT', url, true);xhr.setRequestHeader('X-Custom-Header', 'value');xhr.send();
Dalam kode di atas, metode permintaan HTTP PUT dan mengirim informasi header kustom X-Custom-Header .
Browser menemukan bahwa ini adalah permintaan yang tidak sederhana, sehingga secara otomatis mengeluarkan permintaan "pra-penerbangan", yang mengharuskan server untuk mengonfirmasi bahwa ini dapat diminta. Di bawah ini adalah informasi header HTTP untuk permintaan "preflight" ini.
OPTIONS /cors HTTP/1.1Origin: http://api.bob.comAccess-Control-Request-Method: PUTAccess-Control-Request-Headers: X-Custom-HeaderHost: api.alice.comAccept-Language: en-USConnection: keep-aliveUser-Agent: Mozilla/5.0... Metode permintaan yang digunakan oleh permintaan "preflight" adalah OPTIONS , menunjukkan bahwa permintaan ini digunakan untuk menanyakan. Dalam informasi header, bidang utama adalah Origin , menunjukkan sumber dari permintaan itu berasal.
Selain bidang Origin , informasi header dari permintaan "preflight" mencakup dua bidang khusus.
(1) Method akses-kontrol-kontrol
Bidang ini diperlukan untuk mendaftar metode HTTP mana yang akan digunakan untuk permintaan CORS browser. Contoh di atas PUT .
(2) Access-Control-Request-Headers
Bidang ini adalah string yang dipisahkan koma yang menentukan bidang informasi header tambahan yang akan dikirim oleh permintaan CORS browser. Contoh di atas adalah X-Custom-Header .
4.2 Respons terhadap permintaan pra-penerbangan
Setelah server menerima permintaan "preflight", setelah memeriksa Origin , Access-Control-Request-Method dan bidang Access-Control-Request-Headers , konfirmasi bahwa permintaan silang-asal diperbolehkan, dan Anda dapat merespons.
HTTP/1.1 200 OKDate: Mon, 01 Dec 2008 01:15:39 GMTServer: Apache/2.0.61 (Unix)Access-Control-Allow-Origin: http://api.bob.comAccess-Control-Allow-Methods: GET, POST, PUTAccess-Control-Allow-Headers: X-Custom-HeaderContent-Type: text/html; charset=utf-8Content-Encoding: gzipContent-Length: 0Keep-Alive: timeout=2, max=100Connection: Keep-AliveContent-Type: text/plain
Dalam respons HTTP di atas, kuncinya adalah bidang Access-Control-Allow-Origin , yang berarti http://api.bob.com dapat meminta data. Bidang ini juga dapat diatur ke tanda bintang untuk menyetujui permintaan lintas-asal apa pun.
Access-Control-Allow-Origin: *
Jika browser meniadakan permintaan "preflight", respons HTTP normal akan dikembalikan, tetapi tidak ada bidang header terkait CORS. Pada saat ini, browser akan menentukan bahwa server tidak setuju dengan permintaan preflight, sehingga kesalahan dipicu dan ditangkap oleh fungsi panggilan balik onerror dari objek XMLHttpRequest . Konsol akan mencetak pesan kesalahan berikut.
XMLHttpRequest cannot load http://api.alice.com.Origin http://api.bob.com is not allowed by Access-Control-Allow-Origin.
Bidang terkait CORS lain yang ditanggapi server adalah sebagai berikut.
Access-Control-Allow-Methods: GET, POST, PUTAccess-Control-Allow-Headers: X-Custom-HeaderAccess-Control-Allow-Credentials: trueAccess-Control-Max-Age: 1728000(1) Metode akses-kontrol-terkendali
Bidang ini diperlukan, dan nilainya adalah string yang dipisahkan koma yang menunjukkan semua metode permintaan lintas domain yang didukung oleh server. Perhatikan bahwa semua metode yang didukung dikembalikan, bukan hanya yang diminta oleh browser. Ini untuk menghindari beberapa permintaan "preflight".
(2) Access-control-wallow-headers
Jika permintaan browser mencakup bidang Access-Control-Request-Headers , diperlukan bidang Access-Control-Allow-Headers . Ini juga merupakan string yang dipisahkan koma yang menunjukkan bahwa semua bidang header yang didukung oleh server tidak terbatas pada bidang yang diminta oleh browser di "Preflight".
(3) Access-Control-Allow-Credentials
Bidang ini memiliki arti yang sama seperti saat diminta dengan cara yang sederhana.
(4) Access-Control-Max-Age
Bidang ini opsional dan digunakan untuk menentukan periode validitas dari permintaan preflight ini, dalam hitungan detik. Dalam hasil di atas, periode validitas adalah 20 hari (1728.000 detik), yang berarti bahwa responsnya di -cache selama 1728.000 detik (mis. 20 hari). Selama periode ini, tidak ada permintaan preflight lain yang diperlukan.
4.3 Permintaan dan tanggapan normal dari browser
Setelah server melewati permintaan "preflight", setiap kali permintaan CORS normal browser sama dengan permintaan sederhana, akan ada bidang informasi header Origin . Respons server juga akan memiliki bidang header Access-Control-Allow-Origin .
Di bawah ini adalah permintaan CORS normal dari browser setelah permintaan "preflight".
PUT /cors HTTP/1.1Origin: http://api.bob.comHost: api.alice.comX-Custom-Header: valueAccept-Language: en-USConnection: keep-aliveUser-Agent: Mozilla/5.0...
Bidang Origin informasi header di atas secara otomatis ditambahkan oleh browser.
Di bawah ini adalah respons normal dari server.
Access-Control-Allow-Origin: http://api.bob.comContent-Type: text/html; charset=utf-8
Dalam informasi header di atas, bidang Access-Control-Allow-Origin harus dimasukkan dalam setiap respons.
5. Perbandingan dengan JSONP
CORS digunakan dalam tujuan yang sama dengan JSONP, tetapi lebih kuat dari JSONP.
JSONP hanya mendukung permintaan GET , CORS mendukung semua jenis permintaan HTTP. Keuntungan JSONP adalah mendukung browser kuno dan dapat meminta data dari situs web yang tidak mendukung COR.
(lebih)