HTML5フェッチAPIを使用してAccess-Control-Allow-Originヘッダーを許可する


91

HTML5フェッチAPIを使用しています。

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

通常のjsonを使用できますが、上記のapiURLのデータをフェッチできません。エラーをスローします:

FetchAPIはhttps://davidwalsh.name/demo/arsenal.jsonを読み込めません。要求されたリソースに「Access-Control-Allow-Origin」ヘッダーがありません。したがって、オリジン ' http:// localhost 'はアクセスを許可されていません。不透明な応答がニーズに対応する場合は、リクエストのモードを「no-cors」に設定して、CORSを無効にしてリソースをフェッチします。


サードパーティのサーバーが設定する必要があります。クライアント側でできることは何もありません。
epascarello 2016

@epascarello:クライアント側で行うことができます。舞台裏では、XHRリクエストが進行中です。これを確認してくださいhttps://davidwalsh.name/fetch
iNikkz 2016

回答:


87

epascarelloが言ったように、リソースをホストするサーバーではCORSを有効にする必要があります。クライアント側でできること(そしておそらくあなたが考えていること)は、フェッチのモードをCORSに設定することです(これは私が信じているデフォルト設定ですが):

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

しかし、これはまだCORSを有効にするには、サーバを必要としても、そしてあなたのドメインがリソースを要求することができます。

CORSドキュメントと、同一生成元ポリシーを説明するこの素晴らしいUdacityビデオを確認してください。

クライアント側でno-corsモードを使用することもできますが、これは不透明な応答を提供するだけです(本文を読み取ることはできませんが、応答はサービスワーカーによってキャッシュされたり、のような一部のAPIによって消費されたりする可能性があります<img>) :

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

2
「ただし、サーバーでCORSも有効にし、ドメインがリソースをリクエストできるようにする必要があります。」について詳しく説明していただけますか?私はそれを行うための指示を探すことに失敗しました。
jayscript 2017年

2
@jayscript全体のプロセスは次のようになります。クライアントでは、クロスオリジンリクエストがjavascriptで行われます。フェッチAPIの場合、「cors」モードは、このリクエストを実行しても問題がないことをブラウザに通知します。代わりに「no-cors」モードを使用していた場合、アプリの発信元ではないため、ブラウザーはリクエストを停止します。サーバーはリクエストを受信して​​応答します。ブラウザの応答が適切なCORSヘッダを有し、そしてもしそうであれば、応答を読み取ることを可能にすることを確認します。ヘッダーが存在しない場合、ブラウザはエラーをスローします。
David Scales

1
@jayscriptこのMDNの記事で詳しく説明します。基本的に、必要なサーバーの1つに、次のヘッダーを設定します: "Access-Control-Allow-Origin:foo.example "、 "Access-Control-Allow-Methods:POST、GET、OPTIONS"、 "Access-Control-Allow-Headers: X-PINGOTHER、Content-Type」。これは、オリジン、メソッド、およびヘッダーをそれぞれ有効にします。通常、オリジンヘッダーには「*」が使用されます。このGoogleドキュメントと関連するコードラボをチェックして、Fetch APIについて学ぶこともできます:developers.google.com/web/ilt/pwa/working-with-the-fetch-api
David Scales

2
ありがとうございました!これは、APIサーバーにヘッダーが含まれていない場合、異なるオリジンを持つAPIサーバーからデータをフェッチすることは不可能であることを理解するのに役立ちます。私が扱っていた特定のケースでは、APIサーバーコードにアクセスでき、自分でヘッダーを追加することができました。これにより、フェッチが可能になりました。
jayscript 2017年

これはばかげています、NO sendingCookieのセキュリティ問題とCORSを許可することは何ですか?
deathangel9 0819

13

フロントエンドコードをhttp:// localhost:3000で実行し、API(バックエンドコード)をhttp:// localhost:5000で実行しました

フェッチAPIを使用してAPIを呼び出していました。最初は、「cors」エラーをスローしていました。次に、これをバックエンドAPIコードに追加して、どこからでもオリジンとヘッダーを許可します。

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

ただし、stage、prodなどの他の環境の場合は、発信元を制限する必要があります。


21
これはひどい答えです。これは大きなセキュリティ問題です。これを読んでいる場合は、これを行わないでください。
マットジョーンズ

1
これはローカルセットアップ用です。たとえば、ちょっと簡単な写真を撮る。はい、同じことが他の展開可能な環境にも当てはまる場合、セキュリティリスクがあります。地元のために私はそれがない感じ「あなたは、PROD舞台のような他の環境の場合は、あなたの起源を制限する必要がありますが、」。
smsivaprakaash

12

これは私のために働いた:

npm install -g local-cors-proxy

CORSの問題があるリクエストするAPIエンドポイント:

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

プロキシの開始:

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

 Proxy Active 

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

次に、クライアントコードで、新しいAPIエンドポイント:

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

最終結果は、CORSの問題なしでhttps://www.yourdomain.ie/test/listへのリクエストになります


新しいcmt-promptウィンドウを開き、コードlcp --proxyUrl yourdomain.com
GovarthananVenunathan20年

8

これが古い投稿であることはわかっていますが、このエラーを修正するために機能したのは、フェッチリクエスト内でドメイン名を使用する代わりにサーバーのIPアドレスを使用することでした。したがって、たとえば:

#(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

nginxを使用している場合は、これを試してください

#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

データをリクエストするサーバー側でcorsヘッダーを設定する必要があります。たとえば、バックエンドサーバーがRuby on Railsにある場合は、応答を返す前に次のコードを使用します。すべてのバックエンドサーバーに同じヘッダーを設定する必要があります。

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'

-3

https://expressjs.com/en/resources/middleware/cors.htmlを見てください 。corsを使用する必要があります。

インストール:

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

このコードをノードサーバーに配置する必要があります。


1
それがOPのサーバーであり、NodeJで記述されているかどうかをどうやって知ることができますか?
MarekSzkudelski20年

ノードサーバー(開発モード)を作成した場合は、そのメソッドを使用してjsでフェッチを使用できます。
ErnerstoPastori20年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.