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


88

クロスオリジンのPOSTリクエストを作成しようとしていますが、次の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うまくいかないのか誰かが知っているなら、私たち全員に知らせてください。ありがとう。

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


イオン性フレームワーク3にCORSの問題に直面しながら、これは(Javascriptの者のXMLHttpRequestを使用)私のためのソリューションでした
jeudyx

回答:


73

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


私は答えを見つけたと思います!(4時間と後で多くののろい)

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

受け入れるすべてのヘッダーを手動で指定する必要があります(少なくとも、FF4.0とChrome10.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);
}

5
jQuery1.5.2の動作が変更されていることに注意してください。「X-Requested-With」ヘッダーが追加されなくなったため、これが問題になることはなくなりました。blog.jquery.com/2011/03/31/jquery-152-released(Bug 8423)
Magmatic

1
@TimK、あなたは正しいです!1.5.2をリリースしていることに気づきませんでした。そうは言っても、これはプリフライトが必要な場合にも機能します。回答を更新しました。
メイソンは

だから、私は混乱しています。とにかく中間のPHPスクリプトを書かなければならなくなったのですか?だから、Ajaxの使用について心配する必要はありませんよね?または私は何かが欠けていますか。JavaScriptのみの解決策はありませんか?
エリザベス

1
@Elisabethこのメソッドは、要求された宛先を制御する場合にのみ機能します...これは中間スクリプトではありません。これは、要求された場所のPHPのトップです。それはもっと理にかなっていますか?
メイソン

2
はい!ウィルに感謝します。クライアント側からすべてをコントロールできると思いましたが、両端をコントロールする必要があるようです。
エリザベス

18

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

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

2)dataType: json設定を削除します。jQueryのは、要求しなければならないContent-Type: application/x-www-form-urlencoded、デフォルトではなく、念のために、あなたは置き換えることができdataType: jsoncontentType: 'application/x-www-form-urlencoded'


アイデアをありがとう。私は、データ型を設定して、それがために設定していない試みたapplication/x-www-form-urlencodedとさえtext/plain。そして、Access-Control-Allow-Methods "POST, GET, OPTIONS"Nothingworkedの応答ヘッダーを追加してみました。
マグマ2011

JavaScriptエラーコンソール(またはFirebugのコンソール)を調べて、リクエスト中にエラーが発生していないかどうかを確認できますか?また、Wiresharkの使用方法を知っている場合は、それを使用して、実際のHTTPリクエストがネットワークを通過するのを確認できます。
monsur 2011

1
「もう1つの可能性は、dataType:jsonを設定すると、JQueryがContent-Type:application / jsonヘッダーを送信することです」—これは発生しません。リクエストヘッダーにはdataType影響しますが、Acceptリクエストヘッダーには影響しませんContent-Type
クエンティン

9

あなたは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

1
ごめんなさい。はい。var data = {action:"something"}
マグマ

ここで両方の関数の構文を比較できます:api.jquery.com/jQuery.post
Aleadam

設定のURLで試してみましたが、同じ問題です。.ajax関数はどちらの方法でも使用できます。
マグマ2011

私はすでにそれらのヘッダーのうちの2つを持っていました。他の2つを追加しました。それでもjQueryでは「失敗」します。プレーンなJavaScriptは引き続き機能します。
マグマ2011

私が考えることができる最後のことは、api.jquery.com / jQuery.ajaxSetupを使用jQuery.ajaxSetup({'beforeSend': function(xhr) {xhr.setRequestHeader(string, string)}})して、送信されたさまざまなヘッダーを設定して再生することです(railsの例:railscasts.com/episodes/136-jquery
Aleadam

1

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", "*");

-2

次の方法でJqueryを変更します。

$.ajax({
            url: someurl,
            contentType: 'application/json',
            data: JSONObject,
            headers: { 'Access-Control-Allow-Origin': '*' }, //add this line
            dataType: 'json',
            type: 'POST',                
            success: function (Data) {....}
});

Ajaxカラスを同期させたいのはなぜですか?
RadkoDinev19年

contentType: 'application/json', data: JSONObject,—サーバーはJSONを予期していないため、JSONを送信しても意味がありません。また、JSONオブジェクトのようなものはありません
クエンティン

1
headers: { 'Access-Control-Allow-Origin': '*' }, //add this line絶対にないでください。Access-Control-Allow-Origin応答ヘッダーであり、要求ヘッダーではありません。せいぜいこれは何もしません。最悪の場合、リクエストを単純なリクエストからプリフライトリクエストに変換するため、サーバーでの処理が非常に困難になります。
クエンティン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.