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-Origin
header 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 catch
pemblokiran 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-Origin
header 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-Origin
header 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-Origin
header 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 OPTIONS
permintaan preflight CORS — karena dalam kasus itu, proksi juga mengirimkan kembali Access-Control-Allow-Headers
dan Access-Control-Allow-Methods
header yang diperlukan untuk membuat preflight berhasil.
Cara menghindari preflight CORS
Kode dalam pertanyaan memicu preflight CORS — karena mengirimkan Authorization
header.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests
Bahkan tanpa itu, Content-Type: application/json
tajuk juga akan memicu preflight.
Apa "preflight" artinya: sebelum browser mencoba POST
kode dalam pertanyaan, pertama-tama ia akan mengirim OPTIONS
permintaan ke server - untuk menentukan apakah server memilih ikut menerima lintas asal POST
yang menyertakan Authorization
dan Content-Type: application/json
header.
Ini bekerja cukup baik dengan skrip ikal kecil - saya mendapatkan data saya.
Untuk mengujinya dengan benar curl
, Anda harus meniru OPTIONS
permintaan 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.url
diganti dengan apa pun sign_in
URL Anda yang sebenarnya .
Respons yang perlu dilihat browser dari OPTIONS
permintaan 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 OPTIONS
responsnya tidak menyertakan tajuk tersebut, maka browser akan berhenti di sana dan bahkan tidak pernah mencoba mengirim POST
permintaan. 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 OPTIONS
permintaan dengan kode status 501, yang tampaknya berarti berusaha menunjukkan tidak mengimplementasikan dukungan untuk OPTIONS
permintaan. Server lain biasanya merespons dengan kode status "Metode tidak diizinkan" 405 dalam kasus ini.
Jadi Anda tidak akan pernah dapat membuat POST
permintaan langsung ke server dari kode JavaScript frontend Anda jika server merespons OPTIONS
permintaan 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
Authorization
tajuk permintaan tetapi sebagai gantinya (misalnya) mengandalkan data autentikasi yang disematkan di badan POST
permintaan atau sebagai parameter kueri
- jika server tidak meminta
POST
tubuh untuk memiliki Content-Type: application/json
jenis media, tetapi sebaliknya menerima POST
tubuh sebagai application/x-www-form-urlencoded
dengan 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-Origin
header 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 Origin
header permintaan, dan mengulanginya kembali ke nilai Access-Control-Allow-Origin
header 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-Origin
header 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 -H
seperti 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.
Content-Type
danAccess-Control-Allow-Origin
- terima kasih!open /Applications/Google\ Chrome.app --args --disable-web-security --user-data-dir
Kesalahan ini terjadi ketika URL klien dan URL server tidak cocok, termasuk nomor port. Dalam hal ini Anda perlu mengaktifkan layanan Anda untuk CORS yang merupakan pembagian sumber daya lintas asal.
Jika Anda meng-hosting layanan Spring REST maka Anda dapat menemukannya di posting blog dukungan CORS di Spring Framework .
Jika Anda meng-hosting layanan menggunakan server Node.js, maka
npm install cors --save
Tambahkan baris berikut ke server.js Anda
sumber
including the port number
:(Masalah muncul karena Anda menambahkan kode berikut sebagai header permintaan di front-end Anda:
Header itu milik respons , bukan permintaan. Jadi hapus , termasuk baris:
Permintaan Anda memiliki 'Content-Type: application / json', karenanya memicu apa yang disebut CORS preflight. Ini menyebabkan browser mengirim permintaan dengan metode OPTIONS. Lihat CORS preflight untuk informasi terperinci.
Karenanya di back-end Anda, Anda harus menangani permintaan yang sudah disorot ini dengan mengembalikan header respons yang meliputi:
Tentu saja, sintaksis sebenarnya tergantung pada bahasa pemrograman yang Anda gunakan untuk back-end Anda.
Di front-end Anda, harus seperti ini:
sumber
Dalam kasus saya, saya menggunakan solusi di bawah ini
Front-end atau Angular
back-end (saya menggunakan php)
sumber
Hanya dua sen saya ... tentang Cara menggunakan proxy CORS untuk mengatasi masalah "Tidak ada
Access-Control-Allow-Origin
header"Bagi Anda yang bekerja dengan php di backend, menggunakan "CORS proxy" sesederhana:
buat file bernama 'no-cors.php' dengan konten berikut:
$URL = $_GET['url']; echo json_encode(file_get_contents($URL)); die();
di ujung depan Anda, lakukan sesuatu seperti:
fetch('https://example.com/no-cors.php' + '?url=' + url) .then(response=>{*/Handle Response/*})
sumber
Pindahkan ini:
sumber
Menggunakan
dataType: 'jsonp'
bekerja untuk saya.sumber
Dalam kasus saya, server web mencegah metode "PILIHAN"
Periksa server web Anda untuk metode opsi
mengubah
sumber
Saya bekerja dengan Spring REST, dan saya menyelesaikannya dengan menambahkan DiizinkanMetode ke dalam WebMvcConfigurer.
sumber
Saya mendapatkan kesalahan ini di lokal saya. Saya menjalankan Visual Studio sebagai administrator dan itu diselesaikan.
sumber