6

Backbone.js ベースのアプリを構築していて、奇妙な問題に直面しています。

特定の時点で、アプリがコレクション リソースを要求し、Chrome (および Safari) 内で次のようなエラーが発生します。

XMLHttpRequest cannot load http://api.mydomain.net/v1/foos/00000d/bars/000014/boots Origin http://localhost:3501 is not allowed by Access-Control-Allow-Origin.

わかりました、私が考えたCORSの問題は、私のAPIを非難しました。次に、CURL 経由でこのリソースをリクエストしました。

curl -i -H'Accept: application/json' -H'X-Auth-Token: pAWp5hrCmXA83GgFzgHC' -XOPTIONS 'http://api.mydomain.net/v1/foos/00000d/bars/000014/boots'
HTTP/1.1 200 OK
Status: 200
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Auth-Token
Content-Length: 0

よさそうだ、今GET:

curl -i -H'Accept: application/json' -H'X-Auth-Token: pAWp5hrCmXA83GgFzgHC' -XGET 'http://api.mydomain.net/v1/foos/00000d/bars/000014/boots'
HTTP/1.1 204 No Content
Status: 204
Cache-Control: no-cache
Content-Length: 0
Content-Type: text/plain

少なくとも 1 つのオブジェクトを含むブーツ コレクションをリクエストすると、すべて正常に機能します。サーバーが arr で応答する CORS ヘッダーは、私が思うにまったく問題ありません。では、なぜブラウザーはクロス オリジン リソースの問題を報告するのでしょうか?

text/plain204 応答のコンテンツ タイプが原因ですか?

開発ツールでのプリフライト (OPTIONS) リクエスト: オプション

中止された応答の要求ヘッダー: 得る

4

1 に答える 1

12

Access-Control-Allow-Origin2 番目の要求の応答ヘッダーにも を含める必要があります。これはクライアント側の問題ではなく、バックエンドの問題です。

この動作はCORS 仕様に従っており、次の説明 (セクション 7.1.5「プリフライトを使用したクロスオリジン要求」 )で適用されます。

  1. プリフライトリクエスト(詳細省略)
  2. クロスオリジン リクエストのステータスをプリフライト完了に設定します。」
  3. 「これが実際のリクエストです。(...) リクエストを作成する際は、以下のリクエスト ルールを守ってください。」
    • 応答の HTTP ステータス コードが 301、302、303、または 307 の 場合 該当なし
    • エンドユーザーがリクエストをキャンセルした 場合 該当なし
    • ネットワークエラーの 場合 該当なし
    • そうでない場合は、リソース共有チェックを
      実行します。エラーが返された場合は、キャッシュとネットワーク エラーの手順を適用します。

あなたのリクエストは、リソース共有チェックの最初のステップですでに失敗しています:

  1. 応答にゼロまたは複数のAccess-Control-Allow-Originヘッダー値が含まれている場合は、fail を返し、このアルゴリズムを終了します。

問題を説明する簡単な NodeJS の例を提供します。
現在のバックエンドは次のように動作します。

require('http').createServer(function(request, response) {
    if (request.method == 'OPTIONS') { // Handle preflight
        response.writeHead(200, {
           "Access-Control-Allow-Origin": "*",
           "Access-Control-Allow-Headers": "X-Foo"
        });
    } else {                           // Handle actual requests
        response.writeHead(204, {
          //"Access-Control-Allow-Origin": "*"
        });
    }
    response.end();
}).listen(12345);

ここで、リクエストを行い、失敗を経験します:

var x = new XMLHttpRequest;
x.open('GET', 'http://localhost:12345');
x.setRequestHeader('X-Foo','header to trigger preflight');
x.send();

Access-Control-Allow-Origin提供したコードに戻り、応答でヘッダーを有効にして、もう一度テストします。これでリクエストは成功します。

于 2012-11-10T11:30:23.433 に答える