web-dev-qa-db-ja.com

モードでフェッチとパスを使用しようとしています:no-cors

私はこの終点、Postmanを介してhttp://catfacts-api.appspot.com/api/facts?number=99を打つことができ、それはJSONを返します。

さらに私はcreate-react-appを使用していて、どんなサーバー設定も設定しないようにしたいと思います。

私のクライアントコードでは、同じことをするためにfetchを使用しようとしていますが、エラーが発生します。

要求されたリソースに 'Access-Control-Allow-Origin'ヘッダーがありません。オリジン ' http:// localhost:3000 'はアクセスを許可されていません。不透明な応答がニーズを満たす場合は、CORSを無効にしてリソースを取得するために要求のモードを 'no-cors'に設定します。

そのため、CORSを無効にするオブジェクトをFetchに渡します。

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

興味深いことに、私が得たエラーは実際にはこの関数の構文エラーです。実際のfetchが壊れているかどうかはわかりません。{mode: 'no-cors'}オブジェクトを削除して別のURLを指定しても問題なく動作するからです。

私はまたオブジェクト{ mode: 'opaque'}を渡すことを試みました、しかしこれは上からの元のエラーを返します。

必要なのはCORSを無効にすることだけです。

75
dwww

mode: 'no-cors'を追加しても、魔法のように機能するわけではありません。実際、それは事態を悪化させます。それは、ブラウザに伝えることであるため、「すべての状況下で、フロントエンドJavaScriptコードが応答本文とヘッダーのコンテンツを見るのをブロックします。」もちろん、それはほとんどありませんあなたが欲しいもの。

フロントエンドJavaScriptからのクロスオリジンリクエストで発生することは、ブラウザがデフォルトでフロントエンドコードがクロスオリジンリソースにアクセスすることをブロックすることです。サイトが応答でAccess-Control-Allow-Originを送信すると、ブラウザはそのブロッキングを緩和し、コードが応答にアクセスできるようにします。

ただし、サイトが応答でAccess-Control-Allow-Originヘッダーを送信しない場合、フロントエンドコードがそのサイトからの応答に直接アクセスする方法はありません。特に、mode: 'no-cors'を指定して修正することはできません(実際にはensureフロントエンドコードは応答コンテンツにアクセスできません)。

ただし、willが機能することの1つは、リクエストを CORSプロキシ経由で送信する場合です。このような:

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>

注:https://cors-anywhere.herokuapp.comを使用しようとすると、ダウンしていることがわかった場合、簡単にデプロイすることもできます5つのコマンドを使用して、文字通りわずか2〜3分でHerokuへの独自のプロキシを作成します。

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

これらのコマンドを実行すると、たとえば https://cryptic-headland-94862.herokuapp.com/ で実行される独自のCORS Anywhereサーバーになります。したがって、リクエストURLの前にhttps://cors-anywhere.herokuapp.comを付けるのではなく、独自のインスタンスのURLを前に付けます。例: https://cryptic-headland-94862.herokuapp.com/https://example.com .


このエンドポイントhttp://catfacts-api.appspot.com/api/facts?number=99をヒットすることができます。Postmanを介して

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS は、Postmanで応答にアクセスできるのに、ブラウザーがアクセスを許可しない理由を説明していますレスポンスにAccess-Control-Allow-Originレスポンスヘッダーが含まれていない限り、ウェブアプリで実行されているフロントエンドJavaScriptコードからのクロスレスポンス。

http://catfacts-api.appspot.com/api/facts?number=99 にはAccess-Control-Allow-Originレスポンスヘッダーがないため、フロントエンドコードがクロスレスポンスにアクセスする方法はありません。

ブラウザーは応答を正常に取得でき、Postmanやブラウザー開発ツールでも表示できますが、ブラウザーがそれをコードに公開するわけではありません。 Access-Control-Allow-Origin応答ヘッダーがないため、彼らはしません。そのため、代わりにプロキシを使用して取得する必要があります。

プロキシはそのサイトにリクエストを作成し、レスポンスを取得し、Access-Control-Allow-Originレスポンスヘッダーとその他の必要なCORSヘッダーを追加して、リクエストコードに返します。そして、Access-Control-Allow-Originヘッダーが追加された応答はブラウザに表示されるものなので、ブラウザはフロントエンドコードが実際に応答にアクセスできるようにします。


だから、CORSを無効にするFetchにオブジェクトを渡そうとしています

あなたはそれをしたくありません。明確にするために、「CORSを無効にする」と言うとき、実際には same-Originポリシー を無効にすることを意味しているように見えます。 CORS自体が実際にそれを行う方法です。CORSは、同じ起源のポリシーを緩める方法であり、それを制限する方法ではありません。

しかし、とにかく、ローカル環境だけで、ブラウザーのランタイムフラグを指定してセキュリティを無効にし、安全に実行できないことや、同じ拡張機能ポリシーを回避するためにブラウザー拡張機能をローカルにインストールすることができます。ローカルに状況を変えるだけです.

ローカルでの変更に関係なく、アプリを使用しようとする他のユーザーは引き続き同じ起源ポリシーに違反するため、アプリの他のユーザーに対して無効にすることはできません。

いくつかの限られた場合を除いて、実際にmode: 'no-cors'を使用することはほとんどありません。再実行とその効果は何ですか。これは、mode: 'no-cors'の設定が実際にブラウザに伝えるものが「すべての状況下で、フロントエンドJavaScriptコードが応答本文とヘッダーのコンテンツを見るのをブロックする」からです。」ほとんどの場合、それは明らかに本当にあなたが望むものではありません。


wouldmode: 'no-cors'の使用を検討したい場合は、不透明な応答に適用される制限は?の回答を参照してください。詳細については。その要点は、ケースが次のとおりであるということです。

  • JavaScriptを使用して別のOriginから<script><link rel=stylesheet><img><video><audio>のコンテンツを作成する限られた場合、<object><embed>、または<iframe>要素(これらはクロスオリジンのリソースの埋め込みが許可されているため機能します)-何らかの理由で、したくない、またはできないそのためには、ドキュメントのマークアップでリソースURLを要素のhrefまたはsrc属性として使用するだけです。

  • リソースで実行したいことが、キャッシュすることだけである場合。 不透明な応答にはどのような制限が適用されますか?の回答で示唆されているように、実際に適用されるシナリオは、Service Workerを使用している場合です。この場合、API関連するのは Cache Storage API です。

しかし、これらの限られた場合でも、注意すべき重要な落とし穴がいくつかあります;どのような制限が適用されますか?不透明な応答に?詳細については。


オブジェクト{ mode: 'opaque'}も渡そうとしました。

mode: 'opaque'リクエストモードはありません— opaqueは代わりにresponseのプロパティであり、ブラウザはno-corsで送信されたリクエストからのレスポンスにその不透明プロパティを設定しますモード。

しかし、ちなみに、Word opaqueは、結果として生じる応答の性質に関する非常に明確な信号です。「不透明」は、あなたがそれを見ることができないことを意味します。

139
sideshowbarker

簡単な解決策:データを要求しているphpファイルの一番上に以下を追加してください。

header("Access-Control-Allow-Origin: *");

1

非常に簡単な解決策(設定まで2分)はnpmから local-ssl-proxy パッケージを使うことです

使い方はかなり単純明快です:
1。パッケージをインストールします。npm install -g local-ssl-proxy
2。実行中にlocal-serverlocal-ssl-proxy --source 9001 --target 9000でマスクします

P.S:--target 9000-- "number of your port"に、--source 9001--source "number of your port +1"に置き換えます。

0
volna

あなたが私のようで、Laravel AP​​Iからデータを取得してVueフロントエンドで使用しようとしているlocalhostでWebサイトを開発している場合、これが表示されます問題、ここに私がそれを解決した方法があります:

  1. Laravelプロジェクトで、コマンドphp artisan make:middleware Corsを実行します。これにより、app/Http/Middleware/Cors.phpが作成されます。
  2. Cors.phphandles関数内に次のコードを追加します。

    return $next($request)
        ->header('Access-Control-Allow-Origin', '*')
        ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
    
  3. app/Http/kernel.phpで、$routeMiddleware配列に次のエントリを追加します。

    ‘cors’ => \App\Http\Middleware\Cors::class
    

    (配列にはauthguestなどのような他のエントリがあります。また、Laravelにも別のapp/Http/kernel.phpがあるため、kernel.phpでこれを行っていることを確認してください)

  4. 次のように、アクセスを許可するすべてのルートのルート登録にこのミドルウェアを追加します。

    Route::group(['middleware' => 'cors'], function () {
        Route::get('getData', 'v1\MyController@getData');
        Route::get('getData2', 'v1\MyController@getData2');
    });
    
  5. Vueフロントエンドで、mounted()ではなくdata()関数でこのAPIを呼び出すようにしてください。また、fetch()呼び出しのURLでhttp://またはhttps://を使用するようにしてください。

ピート・ヒューストンの全クレジット ブログ記事

0
dotNET

私にとっての解決策は、それをサーバー側で実行することでした。

C#のWebClientライブラリを使ってデータ(私の場合は画像データ)を取得し、それをクライアントに送り返しました。選択したサーバーサイドの言語におそらく非常によく似たものがあります。

//Server side, api controller

[Route("api/ItemImage/GetItemImageFromURL")]
public IActionResult GetItemImageFromURL([FromQuery] string url)
{
    ItemImage image = new ItemImage();

    using(WebClient client = new WebClient()){

        image.Bytes = client.DownloadData(url);

        return Ok(image);
    }
}

あなたはあなた自身のユースケースが何であれそれを微調整することができます。重要な点はclient.DownloadData()がCORSエラーなしで動いたことです。通常、CORSの問題はWebサイト間でのみ発生するため、サーバーから「クロスサイト」リクエストを送信しても問題ありません。

その場合、Reactフェッチ呼び出しは以下のように単純です。

//React component

fetch(`api/ItemImage/GetItemImageFromURL?url=${imageURL}`, {            
        method: 'GET',
    })
    .then(resp => resp.json() as Promise<ItemImage>)
    .then(imgResponse => {

       // Do more stuff....
    )}
0
Stuart Aitken