web-dev-qa-db-ja.com

CORS POSTリクエストはプレーンなJavaScriptから機能しますが、jQueryを使用しないのはなぜですか?

クロスオリジンの投稿リクエストを作成しようとしていますが、次のようなプレーンなJavascriptで動作します:

var request = new XMLHttpRequest();
var params = "action=something";
request.open('POST', url, true);
request.onreadystatechange = function() {if (request.readyState==4) alert("It worked!");};
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
request.setRequestHeader("Content-length", params.length);
request.setRequestHeader("Connection", "close");
request.send(params);

しかし、jQueryを使用したいのですが、機能しません。これは私が試していることです:

$.ajax(url, {
    type:"POST",
    dataType:"json",
    data:{action:"something"}, 
    success:function(data, textStatus, jqXHR) {alert("success");},
    error: function(jqXHR, textStatus, errorThrown) {alert("failure");}
});

これは失敗に終わります。 jQueryが機能しない理由を誰かが知っている場合は、ご連絡ください。ありがとう。

(私はjQuery 1.5.1とFirefox 4.0を使用しており、サーバーは適切なAccess-Control-Allow-Originヘッダーで応答しています)

82
Magmatic

更新:TimKが指摘したように、jquery 1.5.2ではこれはもう必要ありません。ただし、カスタムヘッダーを追加したり、資格情報(ユーザー名、パスワード、Cookieなど)の使用を許可する場合は、先に進んでください。


私は答えを見つけたと思います! (4時間後に大量の呪い)

//This does not work!!
Access-Control-Allow-Headers: *

受け入れるすべてのヘッダーを手動で指定する必要があります(少なくともFF 4.0およびChrome 10.0.648.204の場合はそうでした)。

jQueryの$ .ajaxメソッドは、すべてのクロスドメインリクエストに対して「x-requested-with」ヘッダーを送信します(クロスドメインのみだと思います)。

そのため、OPTIONSリクエストに応答するために必要なヘッダーがありません:

//no longer needed as of jquery 1.5.2
Access-Control-Allow-Headers: x-requested-with

「単純」でないヘッダーを渡す場合は、それらをリストに含める必要があります(もう1つ送信します)。

//only need part of this for my custom header
Access-Control-Allow-Headers: x-requested-with, x-requested-by

すべてをまとめるために、私のPHPを次に示します。

// * wont work in FF w/ Allow-Credentials
//if you dont need Allow-Credentials, * seems to work
header('Access-Control-Allow-Origin: http://www.example.com');
//if you need cookies or login etc
header('Access-Control-Allow-Credentials: true');
if ($this->getRequestMethod() == 'OPTIONS')
{
  header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
  header('Access-Control-Max-Age: 604800');
  //if you need special headers
  header('Access-Control-Allow-Headers: x-requested-with');
  exit(0);
}
71
Will Mason

別の可能性は、dataType: jsonを設定すると、JQueryがContent-Type: application/jsonヘッダーを送信することです。これはCORSによって非標準ヘッダーと見なされ、CORSプリフライトリクエストが必要です。いくつか試してみること:

1)適切なプリフライト応答を送信するようにサーバーを構成してください。これは、Access-Control-Allow-MethodsAccess-Control-Allow-Headersなどの追加ヘッダーの形式になります。

2)dataType: json設定をドロップします。 JQueryはデフォルトでContent-Type: application/x-www-form-urlencodedを要求する必要がありますが、念のため、dataType: jsoncontentType: 'application/x-www-form-urlencoded'に置き換えることができます。

16
monsur

Jsで「params」を送信しています:request.send(params);

しかし、「jqueryの「データ」」。データは定義されていますか?:data:data,

また、URLにエラーがあります:

$.ajax( {url:url,
         type:"POST",
         dataType:"json",
         data:data, 
         success:function(data, textStatus, jqXHR) {alert("success");},
         error: function(jqXHR, textStatus, errorThrown) {alert("failure");}
});

構文を$ .postの構文と混合しています


更新:私はmonsurの答えに基づいてグーグルで探していましたが、Access-Control-Allow-Headers: Content-Typeを追加する必要があることがわかりました(以下の段落全体)

http://metajack.im/2010/01/19/crossdomain-ajax-for-xmpp-http-binding-made-easy/

CORSの仕組み

CORSは、Flashのcrossdomain.xmlファイルと非常によく似ています。基本的に、ブラウザはクロスドメインリクエストをサービスに送信し、HTTPヘッダーのOriginをリクエストサーバーに設定します。サービスには、そのような要求が許可されているかどうかを示すAccess-Control-Allow-Originなどのヘッダーがいくつか含まれています。

BOSH接続マネージャーの場合、Access-Control-Allow-Originの値を*に設定することにより、すべてのオリジンが許可されることを指定するだけで十分です。 Content-Typeヘッダーは、Access-Control-Allow-Headersヘッダーでホワイトリストに登録する必要もあります。

最後に、BOSH接続マネージャーリクエストを含む特定の種類のリクエストでは、権限チェックが事前に行われます。ブラウザはOPTIONSリクエストを実行し、許可されているオリジン、許可されているメソッド、およびこの許可の有効期間を示すHTTPヘッダーを取得することを期待します。たとえば、私がOPTIONSに対して返したPunjabおよびejabberdのパッチは次のとおりです。

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type 
Access-Control-Max-Age: 86400
8
Aleadam

Corsは、リクエストメソッドを完了する前にPOSTからOPTIONSに変更するため、投稿データは送信されません。このcorsの問題を処理する方法は、OPTIONSメソッドをサポートしないajaxでリクエストを実行することです。サンプルコード:

        $.ajax({
            type: "POST",
            crossdomain: true,
            url: "http://localhost:1415/anything",
            dataType: "json",
            data: JSON.stringify({
                anydata1: "any1",
                anydata2: "any2",
            }),
            success: function (result) {
                console.log(result)
            },
            error: function (xhr, status, err) {
                console.error(xhr, status, err);
            }
        });

c#サーバー上のこのヘッダーで:

                    if (request.HttpMethod == "OPTIONS")
                    {
                          response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With");
                          response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
                          response.AddHeader("Access-Control-Max-Age", "1728000");
                    }
                    response.AppendHeader("Access-Control-Allow-Origin", "*");