jQuery xmlエラー '要求されたリソースに' Access-Control-Allow-Origin 'ヘッダーがありません。


89

私は楽しみのために私の個人的なプロジェクトに取り組んでいます。http: //www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xmlにあるxmlファイルを読み取り、xml を解析し、これを使用して、通貨間の値を変換します。

これまでのところ、xmlを読み取るためのかなり基本的なコードを考え出しましたが、次のエラーが発生します。

XMLHttpRequestは****を読み込めません。要求されたリソースに「Access-Control-Allow-Origin」ヘッダーがありません。したがって、オリジン ' http://run.jsbin.com 'はアクセスを許可されません。

$(document).ready( 
    function() {     
        $.ajax({          
            type:  'GET',
            url:   'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml',
            dataType: 'xml',              
            success: function(xml){
                alert('aaa');
            }
         });
    }
);

私のコードには何の問題もないので、誰かが私のコードで何が間違っているのか、そしてどのようにそれを修正できるかを指摘してほしいと思っています。



エラーは、何が間違っているかを正確に述べています。コードは問題ありませんが、問題はアクセスしているサーバーにあります。
Kevin B

回答:


163

同じ生成元のポリシーにより、でhttp://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xmlデプロイされたファイルからへのajax呼び出しを行うことはできません。http://run.jsbin.com


ソース(別名origin)ページとターゲット URLが異なるドメイン(run.jsbin.comwww.ecb.europa.eu)にあるため、コードは実際には通常のではなくクロスドメイン(CORS)リクエストを作成しようとしていますGET

一言で言えば、同じ生成元のポリシーでは、ブラウザはHTMLページの同じドメインにあるサービスへのajax呼び出しのみを許可するべきであると述べています。


例:

のページは、などのにあるhttp://www.example.com/myPage.htmlサービスのみを直接リクエストできます。サービスが別のドメインでホストされている場合(たとえば)、ブラウザは直接呼び出しを行いません(予想どおり)。代わりに、CORSリクエストを作成しようとします。http://www.example.comhttp://www.example.com/api/myServicehttp://www.ok.com/api/myService

簡単に言えば、さまざまなドメイン間で(CORS)リクエスト*を実行するには、ブラウザで次のようにします。

  • Origin元のリクエストにヘッダーを含め(ページのドメインを値として)、通常どおりに実行します。その後
  • 場合にのみ、サーバーの応答その要求には含まれ(十分なヘッダをAccess-Control-Allow-Originある1それらの CORSを要求することができ、閲覧はコール(ほとんど** HTMLページが同じドメインにあった場合、それが正確だろう道を)完了します。
    • 期待されるヘッダーが表示されない場合、ブラウザーは(あたかもそうであったように)単にあきらめます。


*上記は、ファンシーヘッダーのないレギュラーなどの単純なリクエストの手順を示していますGET。リクエストが単純ではない場合(コンテンツタイプとしてのPOSTwith などapplication/json)、ブラウザはそれをしばらく保持し、それを実行する前に、最初にOPTIONSリクエストをターゲットURLに送信します。上記と同様に、このOPTIONSリクエストへの応答にCORSヘッダーが含まれている場合にのみ続行されます。このOPTIONS呼び出しはプリフライトリクエストと呼ばれます。
**私が言っいるのは、通常の呼び出しとCORS呼び出しの間に他の違いがあるためです。重要なのは、一部のヘッダーは、応答に含まれていても、Access-Control-Expose-Headersヘッダーに含まれていないとブラウザーで取得されないことです。


それを修正するには?

それは単なるタイプミスでしたか?JavaScriptコードのターゲットドメインにタイプミスがある場合があります。確認しましたか?ページが表示されwww.example.comている場合は、定期的にwww.example.com!このような他のURL、api.example.comあるいはexample.comまたはwww.example.com:8080考えられている別のブラウザによってドメイン!はい、ポートが異なる場合、それは異なるドメインです!

ヘッダーを追加します。CORS を有効にする最も簡単な方法は、必要なヘッダーを(Access-Control-Allow-Origin)としてサーバーの応答に追加することです。(各サーバー/言語にはそれを行う方法があります- ここでいくつかの解決策を確認してください。)

最後の手段:サービスへのサーバー側のアクセス権がない場合は、(リバースプロキシなどのツールを使用して)サービスをミラーリングし、そこに必要なヘッダーをすべて含めることもできます


2
ありがとう、それはたくさんの情報です。これで、必要な研究を進めることができます。
Bazinga777 2013年

1
こんにちはacdcjuniorです。アクセスしたいWebサービスをミラーリングするにはどうすればよいですか?
フランバ2014

2
@Franva HTTPサーバー(たとえば、Tomcat、Apache with PHP、IIS with ASP)をセットアップし、そこにページを配置する必要があります。リクエストごとに、実際のサービス(ミラーリングしているサービス)へのソケットを開きます。実際のデータを要求し、それを応答として返します。もちろん、それはコード(Java、PHP、ASPなど)を通じて行います。
acdcjunior 2014

@acdcjunior私の理解が正しければ訂正してください。ブラウザにURLを直接入力すると、Access-Control-Allow-Originなしで自動的に新しいドメインURLにリダイレクトされます。たとえば、WIFを使用する場合、ユーザーは初めてログインしたときにサードパーティのログインページにリダイレクトされます。
マチナリウム2014

@machinarium意味が理解できたのかわかりませんが、答えようとします(何か問題があったら教えてください):ブラウザのアドレスバーにURLを入力するとAccess-Control-Allow-Origin、そのURLの有無がわかりますヘッダーはまったく関係ありません-ブラウザーは通常通りURLを開きます。同一生成元ポリシー(およびAccess-Control-Allow-Originヘッダーの要件)は、Ajax呼び出しにのみ適用されます。
acdcjunior 2014

29

サーバーでphpが有効になっている場合、これを行うための一種のハックタスティックな方法があります。この行を変更します。

url:   'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml',

この行に:

url: '/path/to/phpscript.php',

次に、phpスクリプトで(file_get_contents()関数を使用する権限がある場合):

<?php

header('Content-type: application/xml');
echo file_get_contents("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml");

?>

PHPは、そのURLが別の起源のものであるかどうかを気にしていません。私が言ったように、これはハッキーな答えです、そしてそれが何か問題があると確信していますが、それは私にとってはうまくいきます。

編集:結果をphpにキャッシュしたい場合は、次のphpファイルを使用します。

<?php

$cacheName = 'somefile.xml.cache';
// generate the cache version if it doesn't exist or it's too old!
$ageInSeconds = 3600; // one hour
if(!file_exists($cacheName) || filemtime($cacheName) > time() + $ageInSeconds) {
  $contents = file_get_contents('http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml');
  file_put_contents($cacheName, $contents);
}

$xml = simplexml_load_file($cacheName);

header('Content-type: application/xml');
echo $xml;

?>

キャッシュコードはここから取得します


3
さらに優れたソリューションは、サーバー側でXMLファイルをキャッシュし、file_get_contents最新のXMLファイルの日付が十分である場合にのみ呼び出しを実行することです。また、Content-Typeヘッダーを忘れないでください:-)
sffc

この答えに出くわした。質問:PHPファイルは、GETデータを取得してそれを上記のURLに送信することをどのようにして知るのですか?これはPOSTされたデータでも機能しますか?
mpdc 2014年

提出しません。ファイルを取得してローカルに保存し、そのファイルがローカルでリクエストしているphpファイルであるかのように出力します。ローカルにキャッシュされたファイルが指定された最大保存期間よりも古い場合は、そのコピーを取得して保存します。
2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.