Autoriser l'en-tête Access-Control-Allow-Origin à l'aide de l'API de récupération HTML5

87

J'utilise l'API de récupération 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)
});

Je suis capable d'utiliser json normal mais je ne parviens pas à récupérer les données de l'URL d'API ci-dessus. Il jette une erreur:

L'API de récupération ne peut pas charger https://davidwalsh.name/demo/arsenal.json . Aucun en-tête «Access-Control-Allow-Origin» n'est présent sur la ressource demandée. L' accès d' origine ' http: // localhost ' n'est donc pas autorisé. Si une réponse opaque répond à vos besoins, définissez le mode de la requête sur «no-cors» pour récupérer la ressource avec CORS désactivé.

iNikkz
la source
Le serveur tiers doit le définir, vous ne pouvez rien faire du côté client.
epascarello
@epascarello: Nous pouvons faire du côté client. Dans les coulisses, XHR Request continue. S'il vous plaît vérifier cecihttps://davidwalsh.name/fetch
iNikkz

Réponses:

81

Comme l'a dit epascarello, le serveur qui héberge la ressource doit avoir CORS activé. Ce que vous pouvez faire du côté client (et probablement ce à quoi vous pensez) est de définir le mode de récupération sur CORS (bien que ce soit le paramètre par défaut, je crois):

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

Cependant, cela nécessite toujours que le serveur active également CORS et autorise votre domaine à demander la ressource.

Consultez la documentation CORS et cette superbe vidéo Udacity expliquant la même politique d'origine .

Vous pouvez également utiliser le mode sans cors côté client, mais cela ne vous donnera qu'une réponse opaque (vous ne pouvez pas lire le corps, mais la réponse peut toujours être mise en cache par un service worker ou consommée par certaines API, comme <img>) :

fetch(request, {mode: 'no-cors'})
.then(function(response) {
  console.log(response); 
}).catch(function(error) {  
  console.log('Request failed', error)  
});
David Scales
la source
2
pouvez-vous élaborer sur "Cependant, cela nécessite toujours que le serveur active également CORS et autorise votre domaine à demander la ressource."? J'ai cherché sans succès des instructions pour le faire.
jayscript
2
@jayscript le processus global ressemble à ceci: sur le client, une requête d'origine croisée est effectuée avec javascript. Dans le cas de l'API fetch, le mode «cors» indique au navigateur qu'il peut faire cette demande. Si vous aviez plutôt le mode `` sans cors '', le navigateur arrêterait la demande, car elle ne concerne pas l'origine de votre application. Le serveur recevra la demande et y répondra. Le navigateur confirme que la réponse a les en-têtes CORS appropriés et, le cas échéant, autorise la lecture de la réponse. Si les en-têtes ne sont pas présents, le navigateur lancera une erreur.
David Scales
1
@jayscript cet article MDN entre dans les détails. Essentiellement, vous devez définir ces en-têtes sur votre serveur: "Access-Control-Allow-Origin: foo.example ", "Access-Control-Allow-Methods: POST, GET, OPTIONS", "Access-Control-Allow-Headers: X-PINGOTHER, Content-Type ", qui activent respectivement les origines, les méthodes et les en-têtes. En général, «*» est utilisé pour l'en-tête d'origine. Vous pouvez également consulter ce document Google et le laboratoire de codes associé pour en savoir plus sur l'API Fetch: developer.google.com/web/ilt/pwa/working-with-the-fetch-api
David Scales
2
Merci! Cela m'aide à comprendre qu'il est impossible d'extraire des données du serveur d'API qui ont une origine différente lorsque le serveur d'API ne contient aucun en-tête. Dans le cas particulier auquel je travaillais, j'avais accès au code du serveur API et j'ai pu ajouter des en-têtes par moi-même, ce qui a permis la récupération.
jayscript
C'est idiot, quel est le problème de sécurité avec les NO sendingcookies et autorisant ainsi CORS?
deathangel908
14

J'avais mon code frontal en cours d'exécution dans http: // localhost: 3000 et mon API (code backend) fonctionnant à http: // localhost: 5000

Utilisait Fetch API pour appeler l'API. Au départ, il lançait une erreur "cors". Ensuite, j'ai ajouté ce code ci-dessous dans mon code API Backend, permettant l'origine et l'en-tête de n'importe où.

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

Cependant, vous devez limiter vos origines dans le cas d'autres environnements tels que stage, prod.

smsivaprakaash
la source
20
c'est une réponse terrible. c'est un énorme problème de sécurité. si vous lisez ceci, VEUILLEZ NE PAS FAIRE CELA.
mjones.udri
1
C'est pour la configuration locale. Par exemple pour faire une photo rapide. Oui, il y a un risque de sécurité s'il en va de même pour d'autres environnements déployables. Pour les locaux, je pense que ce n'est pas le cas. "Cependant, vous devriez restreindre vos origines dans le cas d'autres environnements comme stage, prod"
smsivaprakaash
12

Cela a fonctionné pour moi:

npm install -g local-cors-proxy

Point de terminaison d'API que nous voulons demander et qui présente des problèmes CORS:

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

Démarrez le proxy:

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

 Proxy Active 

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

Puis dans votre code client, nouveau point de terminaison d'API:

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

Le résultat final sera une demande à https://www.yourdomain.ie/test/list sans les problèmes CORS!

VigKam
la source
Veuillez vous assurer que le serveur fonctionne en parallèle Comme ouvrez une nouvelle fenêtre d'invite cmt et exécutez le code lcp --proxyUrl votredomaine.com
Govarthanan Venunathan
8

Je sais qu'il s'agit d'un article plus ancien, mais j'ai trouvé que ce qui fonctionnait pour moi pour corriger cette erreur était d'utiliser l'adresse IP de mon serveur au lieu d'utiliser le nom de domaine dans ma demande de récupération. Donc par exemple:

#(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
la source
1

Si vous utilisez nginx, essayez ceci

#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
la source
-3

Regardez https://expressjs.com/en/resources/middleware/cors.html Vous devez utiliser cors.

Installer:

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

Vous devez mettre ce code dans votre serveur de nœuds.

Ernersto Pastori
la source
1
Comment savoir s'il s'agit du serveur d'OP et qu'il est écrit en NodeJs?
Marek Szkudelski le
Si vous avez créé un serveur de nœuds (mode développement), vous pouvez utiliser cette méthode pour utiliser fetch dans js.
Ernersto Pastori le