Izinkan header Access-Control-Allow-Origin menggunakan API pengambilan HTML5

91

Saya menggunakan API pengambilan HTML5.

var request = new Request('https://davidwalsh.name/demo/arsenal.json');

fetch(request).then(function(response) {
    // Convert to JSON
    return response.json();
}).then(function(j) {
    // Yay, `j` is a JavaScript object
    console.log(JSON.stringify(j));
}).catch(function(error) {
    console.log('Request failed', error)
});

Saya dapat menggunakan json normal tetapi tidak dapat mengambil data dari url api di atas. Itu melempar kesalahan:

Fetch API tidak dapat memuat https://davidwalsh.name/demo/arsenal.json . Tidak ada header 'Access-Control-Allow-Origin' yang ada di resource yang diminta. Oleh karena itu, asal ' http: // localhost ' tidak diizinkan untuk diakses. Jika respons buram memenuhi kebutuhan Anda, setel mode permintaan ke 'tanpa cors' untuk mengambil sumber daya dengan CORS dinonaktifkan.

iNikkz
sumber
Server pihak ke-3 perlu mengaturnya, tidak ada yang dapat Anda lakukan di sisi klien.
epascarello
@epascarello: Kita bisa melakukannya di sisi klien. Di belakang layar, Permintaan XHR sedang berlangsung. Silakan periksa inihttps://davidwalsh.name/fetch
iNikkz

Jawaban:

86

Seperti yang dikatakan epascarello, server yang menghosting sumber daya harus mengaktifkan CORS. Apa yang dapat Anda lakukan di sisi klien (dan mungkin apa yang Anda pikirkan) adalah mengatur mode pengambilan ke CORS (meskipun ini adalah pengaturan default yang saya yakini):

fetch(request, {mode: 'cors'});

Namun, ini masih membutuhkan server untuk mengaktifkan CORS juga, dan mengizinkan domain Anda untuk meminta sumber daya.

Lihat dokumentasi CORS , dan video Udacity yang luar biasa ini yang menjelaskan Kebijakan Asal yang Sama .

Anda juga dapat menggunakan mode tanpa cors di sisi klien, tetapi ini hanya akan memberi Anda respons buram (Anda tidak dapat membaca isi, tetapi respons tersebut masih dapat disimpan dalam cache oleh pekerja layanan atau dikonsumsi oleh beberapa API, seperti <img>) :

fetch(request, {mode: 'no-cors'})
.then(function(response) {
  console.log(response); 
}).catch(function(error) {  
  console.log('Request failed', error)  
});
David Scales
sumber
2
dapatkah Anda menjelaskan lebih lanjut tentang "Namun, ini masih memerlukan server untuk mengaktifkan CORS juga, dan mengizinkan domain Anda untuk meminta sumber daya."? Saya tidak berhasil mencari petunjuk untuk melakukan itu.
jayscript
2
@jayscript keseluruhan proses terlihat seperti ini: pada klien, permintaan lintas asal dibuat dengan javascript. Dalam kasus API pengambilan, mode 'cors' memberi tahu browser bahwa tidak masalah membuat permintaan ini. Jika Anda memiliki mode 'tanpa cors', browser akan menghentikan permintaan, karena ini bukan asal aplikasi Anda. Server akan menerima permintaan dan merespon. The Browser menegaskan bahwa respon memiliki CORS header yang sesuai, dan jika demikian, memungkinkan respon untuk dibaca. Jika header tidak ada, browser akan membuat kesalahan.
David Scales
1
@jayscript artikel MDN ini membahas detailnya. Pada dasarnya, salah satu server Anda, Anda perlu menyetel tajuk ini: "Access-Control-Allow-Origin: foo.example ", "Access-Control-Allow-Methods: POST, GET, OPTIONS", "Access-Control-Allow-Headers: X-PINGOTHER, Content-Type ", yang masing-masing mengaktifkan asal, metode, dan header. Biasanya '*' digunakan untuk header asal. Anda juga dapat memeriksa dokumen Google ini dan codelab terkait untuk mempelajari tentang Fetch API: developers.google.com/web/ilt/pwa/working-with-the-fetch-api
David Scales
2
Terima kasih! Itu membantu saya memahami bahwa tidak mungkin mengambil data dari server API yang memiliki asal yang berbeda jika server API tidak berisi header apa pun. Dalam kasus tertentu yang saya hadapi, saya memiliki akses ke kode server API dan dapat menambahkan tajuk sendiri, yang memungkinkan pengambilan.
jayscript
Ini bodoh, apa masalah keamanan dengan NO sendingcookie dan dengan demikian mengizinkan CORS?
deathangel908
13

Saya menjalankan kode front-end saya di http: // localhost: 3000 dan API (kode Backend) saya berjalan di http: // localhost: 5000

Menggunakan fetch API untuk memanggil API. Awalnya, itu melempar kesalahan "cors". Kemudian tambahkan kode di bawah ini dalam kode API Backend saya, memungkinkan asal dan header dari mana saja.

let allowCrossDomain = function(req, res, next) {
  res.header('Access-Control-Allow-Origin', "*");
  res.header('Access-Control-Allow-Headers', "*");
  next();
}
app.use(allowCrossDomain);

Namun Anda harus membatasi asal Anda dalam kasus lingkungan lain seperti panggung, prod.

smsivaprakaash
sumber
21
ini adalah jawaban yang buruk. ini adalah masalah keamanan besar-besaran. jika Anda membaca ini, JANGAN LAKUKAN INI.
Mat Jones
1
Ini hanya untuk pengaturan lokal. Misalnya untuk melakukan quick pic kinda. Ya, ada risiko keamanan jika hal yang sama berlaku untuk lingkungan yang dapat diterapkan lainnya. Untuk lokal saya rasa tidak. "Namun Anda harus membatasi asal Anda dalam kasus lingkungan lain seperti panggung, prod"
smsivaprakaash
12

Ini berhasil untuk saya:

npm install -g local-cors-proxy

Titik akhir API yang ingin kami minta yang memiliki masalah CORS:

https://www.yourdomain.com/test/list

Mulai Proxy:

lcp --proxyUrl https://www.yourdomain.com

 Proxy Active 

 Proxy Url: http://www.yourdomain.com:28080
 Proxy Partial: proxy
 PORT: 8010

Kemudian di kode klien Anda, titik akhir API baru:

http://localhost:8010/proxy/test/list

Hasil akhirnya adalah permintaan ke https://www.yourdomain.ie/test/list tanpa masalah CORS!

VigKam
sumber
Tolong pastikan server berjalan paralel Seperti buka jendela cmt-prompt baru dan jalankan kode lcp --proxyUrl domainanda.com
Govarthanan Venunathan
8

Saya tahu ini adalah posting yang lebih lama, tetapi saya menemukan apa yang berhasil bagi saya untuk memperbaiki kesalahan ini adalah menggunakan alamat IP server saya daripada menggunakan nama domain dalam permintaan pengambilan saya. Jadi contohnya:

#(original) var request = new Request('https://davidwalsh.name/demo/arsenal.json');
#use IP instead
var request = new Request('https://0.0.0.0/demo/arsenal.json');

fetch(request).then(function(response) {
    // Convert to JSON
    return response.json();
}).then(function(j) {
    // Yay, `j` is a JavaScript object
    console.log(JSON.stringify(j));
}).catch(function(error) {
    console.log('Request failed', error)
});
MattG
sumber
1

Jika Anda menggunakan nginx coba ini

#Control-Allow-Origin access

    # Authorization headers aren't passed in CORS preflight (OPTIONS) calls. Always return a 200 for options.
    add_header Access-Control-Allow-Credentials "true" always;
    add_header Access-Control-Allow-Origin "https://URL-WHERE-ORIGIN-FROM-HERE " always;
    add_header Access-Control-Allow-Methods "GET,OPTIONS" always;
    add_header Access-Control-Allow-Headers "x-csrf-token,authorization,content-type,accept,origin,x-requested-with,access-control-allow-origin" always;

    if ($request_method = OPTIONS ) {
        return 200;
    }

Caliari
sumber
1

Anda perlu menyetel cors header di sisi server tempat Anda meminta data. Misalnya jika server backend Anda ada di Ruby on rails, gunakan kode berikut sebelum mengirim respons balik. Header yang sama harus disetel untuk server backend apa pun.

headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST, PUT, DELETE, GET, OPTIONS'
headers['Access-Control-Request-Method'] = '*'
headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Authorization'
Muhammad Saadat Ataa
sumber
-3

Lihat https://expressjs.com/en/resources/middleware/cors.html Anda harus menggunakan cors.

Install:

$ npm install cors
const cors = require('cors');
app.use(cors());

Anda harus meletakkan kode ini di server node Anda.

Ernersto Pastori
sumber
1
Bagaimana Anda bisa tahu apakah itu server OP dan ditulis dalam NodeJs?
Marek Szkudelski
Jika Anda telah membuat server node (mode pengembangan), Anda dapat menggunakan metode itu untuk menggunakan fetch di js.
Ernersto Pastori