web-dev-qa-db-ja.com

Wikipedia API + Cross-Originリクエスト

Javascript + [〜#〜] cors [〜#〜] を使用してウィキペディアにアクセスしようとしています

私の知る限り、ウィキペディアはCORSをサポートする必要があります: http://www.mediawiki.org/wiki/API:Cross-site_requests

次のスクリプトを試してみました。XMLHttpRequest+ credential/XDomainRequestを作成し、いくつかのHttp-Header( "Access-Control-Allow-Credentials"、...)を追加してクエリを送信します。

http://jsfiddle.net/lindenb/Vr7RS/

var WikipediaCORS=
    {
    setMessage:function(msg)
        {
        var span=document.getElementById("id1");
        span.appendChild(document.createTextNode(msg));
        },
    // Create the XHR object.
    createCORSRequest:function(url)
        {
        var xhr = new XMLHttpRequest();


        if ("withCredentials" in xhr)
            {
            xhr.open("GET", url, true);
            }
        else if (typeof XDomainRequest != "undefined")
            {
            xhr = new XDomainRequest();
            xhr.open(method, url);
            }
        else
            {
            return null;
            }
        xhr.setRequestHeader("Access-Control-Allow-Credentials", "true");
        xhr.setRequestHeader("Access-Control-Allow-Origin","*");
        return xhr;
        },
    init:function()
        {
        var _this=this;
        var url = 'http://en.wikipedia.org/w/api.php?action=opensearch&search=Javascript&format=json';
        var xhr = this.createCORSRequest(url);
        if (!xhr)
            {
                this.setMessage('CORS not supported');
                return;
            }

        xhr.onload = function()
            {
                _this.setMessage(xhr.responseText);
            };
        xhr.onerror = function()
            {
                _this.setMessage('Woops, there was an error making the request.');
            };
        xhr.send();
        }
    };

しかし、私のスクリプトは失敗します( 'xhr.onerror'が呼び出されます)。どうすれば修正できますか?

ありがとう。

18
Pierre

CORSヘッダーは、コンテンツへのアクセスを要求するスクリプトを許可するために送信されます。

ウィキペディアはあなたではなくCORSを送信しています。

コメントに従って更新:

一般的なルールの例外としてのWikipedia。要求しているURLにOriginパラメータを追加するように要求する。

これの背後にある理由はキャッシングに関連していると思います。彼らがどのようなメカニズムを使用しているのかはわかりませんが、おそらくキャッシュオブジェクトを格納してバリエーションを構築する方が簡単で良い方法でしょう。


MediaWiki APIドキュメントからのCORSの詳細:

MediaWiki APIでは、Originがリクエストパラメータとして提供され、適切に「Origin」という名前が付けられている必要があります。これは、CORSプロトコルによってOrigin header requiredと照合されます。このヘッダーはフライト前のリクエストに含める必要がありますであるため、POSTリクエストの場合でも、リクエストURIのクエリ文字列部分に含める必要があります。

CORSオリジンチェックに合格した場合、MediaWikiはAccess-Control-Allow-Credentials:trueヘッダーを応答に含めますなので、認証Cookieを送信できます。

これは、ウィキペディアにどこから来たかを伝えるためにOriginヘッダーを送信する必要があることを意味します。 Wikipediaはあなたではなくアクセスを管理しています。

このOriginヘッダーを送信します。

xhr.setRequestHeader("Origin", "http://www.yourpage.com");

Access-Control-Allow-*ヘッダーはresponseヘッダーであり、requestヘッダーではありません。

ウィキペディアではさらに、コンテンツタイプjsonが必要です。

xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
11
Daniel W.

FreeCodeCampプロジェクトでの作業中に同じ問題があり、解決策は非常にシンプルだったので、何時間もかけて検索していたので笑いました。 jQuery URLに以下のパラメーターを含めます。

&Origin=*

作業用コードペン

$.getJSON(
  'https://en.wikipedia.org/w/api.php?action=query&format=json&gsrlimit=15&generator=search' +
  '&Origin=*' + // <-- this is the magic ingredient!
  '&gsrsearch='q, function(data){ /* ... */ }
);
77
Ian De Bie

現在、ウィキペディアは通常のajaxリクエストを使用してCORSリクエストをサポートしています(JSONP /コールバック操作の必要はありません)。これは、API呼び出しでOriginを設定することで実行できます。

認証済みリクエストの場合、これはOriginヘッダーの「origins」の1つと正確に一致する必要があります(ajax呼び出しを行うときにbeforeSendプロパティを使用してこれを設定する必要があります)。
認証されていないリクエストの場合は、アスタリスク(*)として設定するだけでよく、ドメインからの単純な$ .getJSONを使用するときに機能します。 API呼び出しの例:
https://en.wikipedia.org//w/api.php?action=opensearch&format=json&Origin=*&search=stack&limit=10
MediaWiki APIサンドボックスの詳細: MediaWiki APIサンドボックス

15
Adeel Siddiqui

JQuery JSONPを使用できます。

$.ajax( {
    url: "https://en.wikipedia.org/w/api.php",
    jsonp: "callback", 
    dataType: 'jsonp', 
    data: { 
        action: "query", 
        list: "search", 
        srsearch: "javascript", 
        format: "json" 
    },
    xhrFields: { withCredentials: true },
    success: function(response) { ... }
}
5
Aleksandr

URLとともにOrigin=*を追加するだけでは機能しなかったため、withCredentials=falseを追加しました。それが動作します。

Those whoever facing issue again after adding `Origin=*` . Try below one with `withCredentials = false`

var xhttp = new XMLHttpRequest();
var url = "https://en.wikipedia.org/w/api.php?action=opensearch&limit=5&Origin=*&search=simple";
xhttp.onreadystatechange = function () {
    if (readyState == 4 && status == 200) {
        console.log(responseText)
    }
};
xhttp.open("GET", url, true);
xhttp.withCredentials = false;
xhttp.setRequestHeader("Content-type", "application/json; charset=utf-8");
xhttp.send();

@muralivへのクレジット

1
kva