web-dev-qa-db-ja.com

jQuery.getJSON-Access-Control-Allow-Originの問題

JQueryの$.getJSON()関数を使用して、JSONデータの短いセットを返します。

_example.com_などのURLにJSONデータがあります。気付いていませんでしたが、同じURLにアクセスしていたため、JSONデータを読み込むことができませんでした。コンソールをたどると、XMLHttpRequestが_Access-Control-Allow-Origin_のためにロードできなかったことがわかりました。

さて、$.getJSON()を使用すると言われた多くのサイトを読み通しました。これは回避策ですが、明らかに機能しませんでした。ヘッダーまたは関数に変更する必要があるものはありますか?

ヘルプは大歓迎です。

37
Mike

シンプルです。$.getJSON()関数を使用し、URLに

コールバック=?

パラメータとして。それは、クロスドメイン呼び出しを行うために必要なJSONPへの呼び出しを変換します。詳細: http://api.jquery.com/jQuery.getJSON/

73
Hammad Tariq

代わりにJSON-Pを使用することもできます(以下を参照)。まず簡単な説明。

あなたが言及したヘッダーは Cross Origin Resource Sharing 標準のものです。 サポートされていない 人々が実際に使用している一部のブラウザでは注意してください。他のブラウザ(Microsoftのsigh)では、特別なオブジェクト(XDomainRequest)jQueryが使用する標準のXMLHttpRequestではなく。また、サーバー側のリソースを変更して、他のOrigin(www.xxxx.com)。

要求しているJSONデータを取得するには、基本的に3つのオプションがあります。

  1. 可能であれば、ロードするファイルの場所を修正して、ロード先のドキュメントと同じOriginを持つようにすることで、最大限の互換性を確保できます。 (Ajaxを介してそれらをロードする必要があるため、 Same Origin Policy の問題が表示されます。)

  2. JSON-P を使用します。これはSOPの対象ではありません。 jQueryはajax呼び出しでそれを組み込みでサポートしています(dataTypeを「jsonp」に設定するだけで、jQueryはすべてのクライアント側の作業を実行します)。これにはサーバー側の変更が必要ですが、それほど大きな変更は必要ありません。基本的に、JSONレスポンスを生成するものは何でも、「コールバック」と呼ばれるクエリ文字列パラメーターを探し、その関数を呼び出すJavaScriptコードでJSONをラップします。たとえば、現在のJSONレスポンスが次の場合:

    {"weather": "Dreary start but soon brightening into a fine summer day."}
    

    スクリプトは「コールバック」クエリ文字列パラメーターを探し(パラメーターの値が「jsop123」であるとしましょう)、JavaScript関数呼び出しの構文でそのJSONをラップします。

    jsonp123({"weather": "Dreary start but soon brightening into a fine summer day."});
    

    それでおしまい。 JSON-Pはveryと幅広く互換性があります(JavaScript scriptタグを介して機能するため)。 JSON-PはGET専用であり、POST用ではありません(これもscriptタグを介して機能するためです)。

  3. CORS(引用したヘッダーに関連するメカニズム)を使用します。詳細は 上記のリンク仕様 ですが、基本的には:

    A.ブラウザは、OPTIONS HTTP動詞(メソッド)を使用して、サーバーに「プリフライト」メッセージを送信します。 GETまたはPOSTとともに送信するさまざまなヘッダーと、ヘッダー「Origin」、「Access-Control-Request-Method」(たとえば、GETまたはPOST)、および「Access-Control-Request-Headers」(送信するヘッダー)。

    B.あなたのPHPは、その情報に基づいて、リクエストが大丈夫かどうかを判断し、そうであれば「Access-Control-Allow-Origin」、「Access-Control-Allow-Methods」で応答します、および「Access-Control-Allow-Headers」ヘッダーに許可される値が含まれます。その応答で本文(ページ)を送信しないでください。

    C.ブラウザは応答を見て、実際のGETまたはPOSTを送信できるかどうかを確認します。その場合、「Origin」およびさまざまな「Access-Control-Request-xyz」ヘッダーとともに、そのリクエストを送信します。

    D.あなたのPHP=は、それらのヘッダーagainを調べて、それらがまだ問題がないことを確認し、そうであればリクエストに応答します。

    pseudo-code(私はあまりPHPを行っていないので、PHP構文をしようとはしていませんここに):

    // Find out what the request is asking for
    corsOrigin = get_request_header("Origin")
    corsMethod = get_request_header("Access-Control-Request-Method")
    corsHeaders = get_request_header("Access-Control-Request-Headers")
    if corsOrigin is null or "null" {
        // Requests from a `file://` path seem to come through without an
        // Origin or with "null" (literally) as the Origin.
        // In my case, for testing, I wanted to allow those and so I output
        // "*", but you may want to go another way.
        corsOrigin = "*"
    }
    
    // Decide whether to accept that request with those headers
    // If so:
    
    // Respond with headers saying what's allowed (here we're just echoing what they
    // asked for, except we may be using "*" [all] instead of the actual Origin for
    // the "Access-Control-Allow-Origin" one)
    set_response_header("Access-Control-Allow-Origin", corsOrigin)
    set_response_header("Access-Control-Allow-Methods", corsMethod)
    set_response_header("Access-Control-Allow-Headers", corsHeaders)
    if the HTTP request method is "OPTIONS" {
        // Done, no body in response to OPTIONS
        stop
    }
    // Process the GET or POST here; output the body of the response
    

    繰り返しますが、これは擬似コードであることを強調します。

38
T.J. Crowder