Jawaban ini mencakup banyak landasan, sehingga terbagi menjadi tiga bagian:
- Cara menggunakan proxy CORS untuk berkeliling “Tidak Access-Control-Allow-Origin header” masalah
- Cara menghindari preflight CORS
- Cara untuk memperbaiki “Access-Control-Allow-Origin sundulan tidak harus menjadi wildcard” masalah
Cara menggunakan proxy CORS untuk berkeliling “Tidak Access-Control-Allow-Origin header” masalah
Jika Anda tidak mengontrol server, kode JavaScript frontend Anda mengirim permintaan ke, dan masalah dengan respons dari server itu hanya kurangnya Access-Control-Allow-Originheader yang diperlukan , Anda masih bisa menyelesaikan pekerjaan — dengan membuat permintaan melalui Proxy CORS. Untuk menunjukkan cara kerjanya, pertama-tama inilah beberapa kode yang tidak menggunakan proxy CORS:
const url = "https://example.com"; // site that doesn’t send Access-Control-*
fetch(url)
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))
Alasan catchpemblokiran ada di sana adalah, browser mencegah kode itu dari mengakses tanggapan yang datang kembali https://example.com. Dan alasan browser melakukan itu adalah, responsnya kurang memiliki Access-Control-Allow-Originheader respons.
Sekarang, inilah contoh yang persis sama tetapi hanya dengan proxy CORS ditambahkan:
const proxyurl = "https://cors-anywhere.herokuapp.com/";
const url = "https://example.com"; // site that doesn’t send Access-Control-*
fetch(proxyurl + url) // https://cors-anywhere.herokuapp.com/https://example.com
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))
Catatan: Jika https://cors-anywhere.herokuapp.com sedang down atau tidak tersedia saat Anda mencobanya, maka lihat di bawah ini bagaimana cara menyebarkan server CORS Anywhere Anda sendiri di Heroku hanya dalam 2-3 menit.
Cuplikan kode kedua di atas dapat mengakses respons dengan sukses karena mengambil URL permintaan dan mengubahnya ke https://cors-anywhere.herokuapp.com/https://example.com —dengan hanya mengawalinya dengan URL proxy — menyebabkan meminta dilakukan melalui proxy itu, yang kemudian:
- Meneruskan permintaan ke
https://example.com.
- Menerima tanggapan dari
https://example.com.
- Menambahkan
Access-Control-Allow-Originheader ke respons.
- Lewati respons itu, dengan header tambahan itu, kembali ke kode frontend yang meminta.
Browser kemudian memungkinkan kode frontend untuk mengakses respons, karena respons dengan Access-Control-Allow-Originheader respons itulah yang dilihat browser.
Anda dapat dengan mudah menjalankan proxy Anda sendiri menggunakan kode dari https://github.com/Rob--W/cors-anywhere/ .
Anda juga dapat dengan mudah menggunakan proksi Anda sendiri ke Heroku hanya dalam 2-3 menit, dengan 5 perintah:
git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master
Setelah menjalankan perintah-perintah itu, Anda akan berakhir dengan server CORS Anywhere Anda berjalan di, misalnya, https://cryptic-headland-94862.herokuapp.com/ . Jadi, alih-alih awalan dengan URL permintaan Anda https://cors-anywhere.herokuapp.com, awali dengan URL untuk instance Anda sendiri; mis., https://cryptic-headland-94862.herokuapp.com/https://example.com .
Jadi jika ketika Anda mencoba menggunakan https://cors-anywhere.herokuapp.com, Anda merasa sedang down (yang kadang-kadang akan terjadi), maka pertimbangkan untuk mendapatkan akun Heroku (jika belum) dan ambil 2 atau 3 menit untuk melakukan langkah-langkah di atas untuk menggunakan server CORS Anywhere Anda sendiri di Heroku.
Terlepas dari itu, apakah Anda menjalankan sendiri atau menggunakan https://cors-anywhere.herokuapp.com atau proxy terbuka lainnya, solusi ini berfungsi bahkan jika permintaannya adalah yang memicu browser untuk melakukan OPTIONSpermintaan preflight CORS — karena dalam kasus itu, proksi juga mengirimkan kembali Access-Control-Allow-Headersdan Access-Control-Allow-Methodsheader yang diperlukan untuk membuat preflight berhasil.
Cara menghindari preflight CORS
Kode dalam pertanyaan memicu preflight CORS — karena mengirimkan Authorizationheader.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests
Bahkan tanpa itu, Content-Type: application/jsontajuk juga akan memicu preflight.
Apa "preflight" artinya: sebelum browser mencoba POSTkode dalam pertanyaan, pertama-tama ia akan mengirim OPTIONSpermintaan ke server - untuk menentukan apakah server memilih ikut menerima lintas asal POSTyang menyertakan Authorizationdan Content-Type: application/jsonheader.
Ini bekerja cukup baik dengan skrip ikal kecil - saya mendapatkan data saya.
Untuk mengujinya dengan benar curl, Anda harus meniru OPTIONSpermintaan preflight yang dikirimkan browser:
curl -i -X OPTIONS -H "Origin: http://127.0.0.1:3000" \
-H 'Access-Control-Request-Method: POST' \
-H 'Access-Control-Request-Headers: Content-Type, Authorization' \
"https://the.sign_in.url"
... dengan https://the.sign_in.urldiganti dengan apa pun sign_inURL Anda yang sebenarnya .
Respons yang perlu dilihat browser dari OPTIONSpermintaan itu harus menyertakan tajuk seperti ini:
Access-Control-Allow-Origin: http://127.0.0.1:3000
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type, Authorization
Jika OPTIONSresponsnya tidak menyertakan tajuk tersebut, maka browser akan berhenti di sana dan bahkan tidak pernah mencoba mengirim POSTpermintaan. Selain itu, kode status HTTP untuk respons harus berupa 2xx — biasanya 200 atau 204. Jika ada kode status lain, peramban akan berhenti di sana.
Server dalam pertanyaan merespons OPTIONSpermintaan dengan kode status 501, yang tampaknya berarti berusaha menunjukkan tidak mengimplementasikan dukungan untuk OPTIONSpermintaan. Server lain biasanya merespons dengan kode status "Metode tidak diizinkan" 405 dalam kasus ini.
Jadi Anda tidak akan pernah dapat membuat POSTpermintaan langsung ke server dari kode JavaScript frontend Anda jika server merespons OPTIONSpermintaan itu dengan 405 atau 501 atau apa pun selain 200 atau 204 atau jika tidak menanggapi dengan yang diperlukan header respons.
Cara untuk menghindari memicu preflight untuk kasus dalam pertanyaan adalah:
- jika server tidak memerlukan
Authorizationtajuk permintaan tetapi sebagai gantinya (misalnya) mengandalkan data autentikasi yang disematkan di badan POSTpermintaan atau sebagai parameter kueri
- jika server tidak meminta
POSTtubuh untuk memiliki Content-Type: application/jsonjenis media, tetapi sebaliknya menerima POSTtubuh sebagai application/x-www-form-urlencodeddengan parameter bernama json(atau apa pun) yang nilainya adalah data JSON
Cara untuk memperbaiki “Access-Control-Allow-Origin sundulan tidak harus menjadi wildcard” masalah
Saya mendapatkan pesan kesalahan lain:
Nilai tajuk 'Akses-Kontrol-Bolehkan-Asal' dalam respons tidak boleh berupa wildcard '*' ketika mode kredensial permintaan adalah 'sertakan'. Origin ' http://127.0.0.1:3000 ' karenanya tidak diperbolehkan mengakses. Mode kredensial permintaan yang dimulai oleh XMLHttpRequest dikendalikan oleh atribut withCredentials.
Untuk permintaan yang menyertakan kredensial, browser tidak akan membiarkan kode JavaScript frontend Anda mengakses respons jika nilai Access-Control-Allow-Originheader responsnya *. Sebaliknya nilai dalam kasus itu harus sama persis dengan asal kode frontend Anda http://127.0.0.1:3000,.
Lihat permintaan terredensial dan wildcard di artikel MDN HTTP access control (CORS).
Jika Anda mengontrol server yang Anda kirimi permintaan, maka cara umum untuk menangani kasus ini adalah mengonfigurasi server untuk mengambil nilai Originheader permintaan, dan mengulanginya kembali ke nilai Access-Control-Allow-Originheader respons. Misalnya, dengan nginx:
add_header Access-Control-Allow-Origin $http_origin
Tapi itu hanya satu contoh; sistem server (web) lainnya menyediakan cara yang serupa untuk mengumandangkan nilai asal.
Saya menggunakan Chrome. Saya juga mencoba menggunakan Plugin Chrome CORS itu
Plugin Chrome CORS itu tampaknya hanya menyuntikkan Access-Control-Allow-Origin: *header secara sederhana ke respons yang dilihat browser. Jika plugin lebih pintar, apa yang akan dilakukannya adalah mengatur nilai Access-Control-Allow-Originheader respons palsu itu ke asal sebenarnya kode JavaScript frontend Anda http://127.0.0.1:3000,.
Jadi hindari menggunakan plugin itu, bahkan untuk pengujian. Itu hanya gangguan. Jika Anda ingin menguji tanggapan apa yang Anda dapatkan dari server tanpa peramban menyaringnya, Anda lebih baik menggunakan curl -Hseperti di atas.
Sejauh kode JavaScript frontend untuk fetch(…)permintaan dalam pertanyaan:
headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');
Hapus garis itu. The Access-Control-Allow-*header respon header. Anda tidak pernah ingin mengirim mereka dalam permintaan. Satu-satunya efek yang akan dimiliki adalah memicu browser untuk melakukan preflight.