Essayer d'utiliser fetch et passer en mode: no-cors

je peux frapper ce point de terminaison, http://catfacts-api.appspot.com/api/facts?number=99 par Facteur et il retourne JSON

de plus, j'utilise create-react-app et je voudrais éviter de configurer n'importe quelle configuration de serveur.

Dans mon code, je suis en train d'utiliser fetch pour faire la même chose, mais j'obtiens l'erreur:

Non "Access-Control-Allow-Origin' en-tête est présent sur le demandé ressources. Origine " http://localhost:3000 " n'est donc pas autorisé accès. Si une réponse opaque répond à vos besoins, définissez la en mode "non-scro' pour aller chercher la ressource avec la SCRO désactivé.

donc j'essaie de passer dans un objet, à mon Fetch qui va désactiver CORS, comme ça:

fetch('http://catfacts-api.appspot.com/api/facts?number=99', { mode: 'no-cors'})
  .then(blob => blob.json())
  .then(data => {
    console.table(data);
    return data;
  })
  .catch(e => {
    console.log(e);
    return e;
  });

assez intéressant, l'erreur que j'obtiens est en fait une erreur de syntaxe avec cette fonction. Je ne suis pas sûr que mon fetch soit cassé, parce que lorsque je supprime l'objet { mode: 'no-cors'}, et que je le fournis avec une URL différente, il fonctionne très bien.

j'ai aussi essayé de passer dans l'objet { mode: 'opaque'} , mais cela renvoie l'erreur originale d'en haut.

je crois que tout ce que je dois faire c'est désactiver CORS.. Ce qui me manque?

40
demandé sur sideshowbarker 2017-04-06 20:36:05

1 réponses

ajouter mode: 'no-cors' ne fera pas fonctionner les choses par magie. Les navigateurs par défaut bloquent le code frontend de l'accès aux ressources cross-origin. Si un site envoie Access-Control-Allow-Origin dans ses réponses, alors les navigateurs relâcheront ce blocage et permettront à votre code d'accéder à la réponse.

mais si un site n'envoie pas l'en-tête Access-Control-Allow-Origin dans ses réponses, alors il n'y a aucun moyen que votre code JavaScript frontal puisse accéder directement aux réponses à partir de ce site. Notamment, le fait de spécifier mode: 'no-cors' ne corrigera pas cela (en fait, cela ne fera qu'empirer les choses).

cependant, une chose que fonctionnera est si vous envoyez votre demande par un proxy CORS , comme ceci:

var proxyUrl = 'https://cors-anywhere.herokuapp.com/',
    targetUrl = 'http://catfacts-api.appspot.com/api/facts?number=99'
fetch(proxyUrl + targetUrl)
  .then(blob => blob.json())
  .then(data => {
    console.table(data);
    document.querySelector("pre").innerHTML = JSON.stringify(data, null, 2);
    return data;
  })
  .catch(e => {
    console.log(e);
    return e;
  });
<pre></pre>

Note: Si vous allez à essayer d'utiliser https://cors-anywhere.herokuapp.com, vous trouvez qu'il est en bas , vous pouvez également déployer facilement votre propre mandataire à Heroku en littéralement seulement 2-3 minutes, avec 5 commandes:

git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master

après avoir exécuté ces commandes, vous finirez avec votre propre serveur CORS N'importe où sur, par exemple, https://cryptic-headland-94862.herokuapp.com / . Ainsi, plutôt que de préfixer L'URL de votre requête avec https://cors-anywhere.herokuapp.com , préfixez-la avec L'URL de votre propre instance; par exemple, https://cryptic-headland-94862.herokuapp.com/https://example.com .


je peux atteindre ce point final, http://catfacts-api.appspot.com/api/facts?number=99 via Postman et il retourne JSON

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS explique pourquoi même si vous pouvez accéder à la réponse avec Postman, les navigateurs ne vous permettront pas d'accéder à la réponse cross-origin à partir du code JavaScript frontend en cours d'exécution dans une application web sauf si la réponse comprend un en-tête de réponse Access-Control-Allow-Origin .

http://catfacts-api.appspot.com/api/facts?number=99 n'a pas d'en-tête de réponse Access-Control-Allow-Origin , donc il n'y a aucun moyen que votre code frontal puisse accéder à la réponse cross-origin.

votre navigateur peut obtenir la réponse fine et vous pouvez le voir dans Postman et même dans les devtools navigateur-mais cela ne signifie pas que les navigateurs vont l'exposer à votre code. Ils ne sont pas, parce qu'il a pas d'en-tête de réponse Access-Control-Allow-Origin . Vous devez donc utiliser un mandataire pour l'obtenir.

le mandataire fait la demande à ce site, obtient la réponse, ajoute l'en-tête de réponse Access-Control-Allow-Origin et tous les autres en-têtes CORS nécessaires, puis passe que de nouveau à votre code de demande. Et cette réponse avec l'en-tête Access-Control-Allow-Origin ajouté Est ce que le navigateur voit, donc le navigateur permet à votre code frontal effectivement accéder à la réponse.


donc j'essaie de passer dans un objet, à mon Fetch qui va désactiver CORS

tu ne veux pas faire ça. Pour être clair, quand vous dites que vous voulez "désactiver CORS", il semble que vous voulez en fait désactiver la Politique de même origine . CORS lui - même est en fait un moyen de le faire-CORS est un moyen d'assouplir la Politique de même origine, pas un moyen de la restreindre.

mais de toute façon, il est vrai que vous pouvez votre environnement local - faites des choses comme donner à votre navigateur des indicateurs runtime pour désactiver la sécurité et exécuter de manière sûre, ou vous pouvez installer une extension de navigateur localement pour contourner la Politique de même origine, mais tout ce qui fait est de changer la situation juste pour vous localement.

peu importe ce que vous changez localement, n'importe qui d'autre essayant d'utiliser votre application va toujours tomber dans la même politique d'origine, et il n'y a aucun moyen que vous puissiez désactiver cela pour les autres utilisateurs de votre application.

vous ne voulez probablement jamais utiliser mode: 'no-cors' dans la pratique sauf dans quelques cas limités , et même alors seulement si vous savez exactement ce que vous faites et quels sont les effets. C'est parce que le réglage mode: 'no-cors' dit en fait au navigateur est, "empêcher mon code JavaScript frontal de regarder dans le contenu du corps de réponse et des en-têtes dans toutes les circonstances." dans la plupart des cas, ce n'est évidemment pas ce que vous vouloir.


en ce qui concerne les cas où vous est-ce que "voulez envisager d'utiliser mode: 'no-cors' , voir la réponse à Quelles limites s'appliquent aux réponses opaques? pour les détails. L'essentiel est que les cas sont:

  • dans le cas limité où vous utilisez JavaScript pour faire une ressource d'une autre origine le contenu de a <script> , <link rel=stylesheet> , <img> , <video> , <audio> , <object> , <embed> , ou <iframe> élément (qui fonctionne parce que l'intégration des ressources cross-origin est autorisé pour ceux) - mais pour une raison quelconque, vous ne voulez pas ou ne pouvez pas le faire simplement en ayant le markup du document Utiliser L'URL de la ressource comme l'attribut href ou src pour l'élément.

  • Quand la seule chose que vous voulez faire avec une ressource est à mettre en cache. Comme il est mentionné dans la réponse à , quelles sont les limites applicables aux réponses opaques? , en pratique le scénario qui s'applique est lorsque vous utilisez des travailleurs de Service, auquel cas L'API qui est pertinent est le Cache Storage API .

; voir la réponse à quelles sont les limites applicables aux réponses opaques? pour les détails.


j'ai également essayé de passer dans l'objet { mode: 'opaque'}

il n'y a pas de mode: 'opaque' mode requête-la condition opaque est plutôt juste une propriété de la réponse , et les navigateurs régler que opaque condition sur les réponses si elles sont de demandes qui sont envoyées avec le no-cors mode.

mais d'ailleurs le mot opaque est un signal assez clair sur la nature de la réponse que vous obtenez avec:" opaque " signifie que vous ne pouvez pas le voir.

59
répondu sideshowbarker 2018-10-04 20:42:34