Consenti intestazione Access-Control-Allow-Origin utilizzando l'API di recupero HTML5


91

Sto utilizzando l'API di recupero 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)
});

Sono in grado di utilizzare json normale ma non sono in grado di recuperare i dati dell'URL API di cui sopra. Genera errore:

Fetch API non può caricare https://davidwalsh.name/demo/arsenal.json . Nessuna intestazione "Access-Control-Allow-Origin" è presente sulla risorsa richiesta. L'accesso all'origine " http: // localhost " non è pertanto consentito. Se una risposta opaca soddisfa le tue esigenze, imposta la modalità della richiesta su "no-cors" per recuperare la risorsa con CORS disabilitato.


Il server di terze parti deve impostarlo, non puoi fare nulla sul lato client.
epascarello

@epascarello: Possiamo fare al lato client. Dietro le quinte, la richiesta XHR è in corso. Si prega di controllare questohttps://davidwalsh.name/fetch
iNikkz

Risposte:


86

Come ha detto epascarello, il server che ospita la risorsa deve avere CORS abilitato. Quello che puoi fare sul lato client (e probabilmente quello a cui stai pensando) è impostare la modalità di recupero su CORS (sebbene questa sia l'impostazione predefinita, credo):

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

Tuttavia, ciò richiede ancora che il server abiliti anche CORS e consenta al tuo dominio di richiedere la risorsa.

Guarda la documentazione CORS e questo fantastico video di Udacity che spiega la politica della stessa origine .

Puoi anche utilizzare la modalità no-cors sul lato client, ma questo ti darà solo una risposta opaca (non puoi leggere il corpo, ma la risposta può ancora essere memorizzata nella cache da un addetto all'assistenza o consumata da alcune API, come <img>) :

fetch(request, {mode: 'no-cors'})
.then(function(response) {
  console.log(response); 
}).catch(function(error) {  
  console.log('Request failed', error)  
});

2
puoi approfondire "Tuttavia questo richiede ancora che il server abiliti anche CORS e consenta al tuo dominio di richiedere la risorsa."? Ho cercato senza successo le istruzioni per farlo.
jayscript

2
@jayscript il processo complessivo è simile a questo: sul client, viene effettuata una richiesta di origine incrociata con javascript. Nel caso dell'API fetch, la modalità 'cors' dice al browser che va bene fare questa richiesta. Se invece avessi la modalità "no-cors", il browser interromperà la richiesta, perché non è all'origine della tua app. Il server riceverà la richiesta e risponderà. Il browser conferma che la risposta ha le intestazioni CORS appropriate e, in tal caso, consente la lettura della risposta. Se le intestazioni non sono presenti, il browser genererà un errore.
David Scales

1
@jayscript questo articolo MDN entra nei dettagli. In sostanza, sul tuo server devi impostare queste intestazioni: "Access-Control-Allow-Origin: foo.example ", "Access-Control-Allow-Methods: POST, GET, OPTIONS", "Access-Control-Allow-Headers: X-PINGOTHER, Content-Type ", che abilitano rispettivamente origini, metodi e intestazioni. Tipicamente "*" viene utilizzato per l'intestazione di origine. Puoi anche controllare questo documento Google e il codelab associato per conoscere l'API Fetch: developers.google.com/web/ilt/pwa/working-with-the-fetch-api
David Scales

2
Grazie! Questo mi aiuta a capire che è impossibile recuperare i dati dal server API che ha un'origine diversa quando il server API non contiene intestazioni. Nel caso particolare di cui avevo a che fare, avevo accesso al codice del server API e potevo aggiungere le intestazioni da solo, il che abilitava il recupero.
jayscript

Questo è stupido, qual è il problema di sicurezza con i NO sendingcookie e quindi consentendo CORS?
deathangel908

13

Avevo il mio codice front-end in esecuzione in http: // localhost: 3000 e la mia API (codice backend) in esecuzione in http: // localhost: 5000

Utilizzava l'API di recupero per chiamare l'API. Inizialmente, stava lanciando l'errore "cors". Quindi ho aggiunto questo codice sotto nel mio codice API backend, consentendo origine e intestazione da qualsiasi luogo.

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

Tuttavia dovresti limitare le tue origini in caso di altri ambienti come stage, prod.


21
questa è una risposta terribile. questo è un enorme problema di sicurezza. se stai leggendo questo, PER FAVORE, NON FARE QUESTO.
Mat Jones,

1
Questo è solo per la configurazione locale. Ad esempio per fare una foto veloce. Sì, c'è un rischio per la sicurezza se lo stesso vale per altri ambienti distribuibili. Per i locali credo di no. "Tuttavia dovresti limitare le
tue

12

Questo ha funzionato per me:

npm install -g local-cors-proxy

Endpoint API che vogliamo richiedere con problemi CORS:

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

Avvia proxy:

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

 Proxy Active 

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

Quindi nel codice client, nuovo endpoint API:

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

Il risultato finale sarà una richiesta a https://www.tuodominio.ie/test/list senza i problemi CORS!


Assicurati che il server sia in esecuzione in parallelo Come aprire la nuova finestra del prompt di cmt ed eseguire il codice lcp --proxyUrl yourdomain.com
Govarthanan Venunathan

8

So che questo è un post precedente, ma ho scoperto che ciò che ha funzionato per me per correggere questo errore è stato l'utilizzo dell'indirizzo IP del mio server invece di utilizzare il nome di dominio nella mia richiesta di recupero. Quindi per esempio:

#(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)
});

1

Se usi nginx prova questo

#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;
    }


1

È necessario impostare l'intestazione cors sul lato server da cui si richiedono i dati. Ad esempio, se il tuo server di backend è in Ruby on rails, usa il seguente codice prima di inviare la risposta. Le stesse intestazioni dovrebbero essere impostate per qualsiasi server di backend.

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'

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.