web-dev-qa-db-ja.com

FirefoxでREQUEST_METHODとして "OPTIONS"を送信するjQuery $ .ajax()、$ .post

比較的単純なjQueryプラグインだと思ったことに問題があります。

プラグインは<select>にオプションを追加するためにajax経由でphpスクリプトからデータを取得するべきです。 ajaxリクエストはかなり一般的です。

$.ajax({
  url: o.url,
  type: 'post',
  contentType: "application/x-www-form-urlencoded",
  data: '{"method":"getStates", "program":"EXPLORE"}',
  success: function (data, status) {
    console.log("Success!!");
    console.log(data);
    console.log(status);
  },
  error: function (xhr, desc, err) {
    console.log(xhr);
    console.log("Desc: " + desc + "\nErr:" + err);
  }
});

これはSafariではうまくいくようです。 Firefox 3.5では、サーバー上のREQUEST_TYPEは常に 'OPTIONS'であり、$ _POSTデータは表示されません。 Apacheはリクエストをタイプ 'OPTIONS'として記録します。

::1 - - [08/Jul/2009:11:43:27 -0500] "OPTIONS sitecodes.php HTTP/1.1" 200 46

このajax呼び出しはなぜFirefoxではなくSafariで機能するのですか。また、Firefoxでどのように修正するのですか?

レスポンスヘッダー
日付:2009年7月8日水曜日21:22:17 GMT 
サーバー:Apache/2.0.59(Unix)PHP/5.2.6 DAV/2 
 X-Powered-By:PHP/5.2.6 
コンテンツ長46 
キープアライブタイムアウト= 15、最大= 100 
接続キープアライブ
 [] Content-Type text/html 
 
リクエストヘッダ
ホストオーダーフォーム:8888 
ユーザエージェントMozilla/5.0(Macintosh; U; Intel Mac OS X 10.5) ; ja-US; rv:1.9.1)Gecko/20090624 Firefox/3.5 
 text/html、application/xhtml + xml、application/xmlを受け入れる; q = 0.9、*/*; q = 0.8 [。 Accept-Language en-us、en; q = 0.5 
 Accept-Encoding gzip、deflate 
 Accept-Charset ISO-8859-1、utf-8、q = 0.7、*。 q = 0.7 
キープアライブ300 
接続キープアライブ
原点http://ux.inetu.act.org 
アクセス制御要求メソッドPOST 
アクセス制御要求ヘッダーx-requested-with 

これがFirebugの出力の図です。

326

エラーの原因は同じOriginポリシーです。それはあなたがあなた自身のドメインにXMLHTTPRequestsをすることを可能にするだけです。代わりに JSONP コールバックを使用できるかどうかを確認してください。

$.getJSON( 'http://<url>/api.php?callback=?', function ( data ) { alert ( data ); } );
167
Jonas Skovmand

私はDjango側で以下のコードを使用してOPTIONSリクエストを解釈し、必要なAccess-Controlヘッダーを設定しました。この後、Firefoxからのクロスドメインリクエストが機能し始めました。前述のように、ブラウザは最初にOPTIONSリクエストを送信し、次にその直後にPOST/GETコマンドを送信します。

def send_data(request):
    if request.method == "OPTIONS": 
        response = HttpResponse()
        response['Access-Control-Allow-Origin'] = '*'
        response['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
        response['Access-Control-Max-Age'] = 1000
        # note that '*' is not valid for Access-Control-Allow-Headers
        response['Access-Control-Allow-Headers'] = 'Origin, x-csrftoken, content-type, accept'
        return response
    if request.method == "POST":
        # ... 

編集:少なくともいくつかのケースでは、実際のレスポンスにも同じAccess-Controlヘッダを追加する必要があるようです。リクエストは成功したように見えますが、Firefoxはレスポンスの内容をJavascriptに渡しません。

56
Juha Palomäki

この mozillaデベロッパーセンターの記事 はクロスドメインリクエストのさまざまなシナリオについて説明しています。この記事は、コンテンツタイプが 'application/x-www-form-urlencoded'のPOST要求は、(単純な要求ではなく)単純な要求として送信する必要があることを示しているようです。ただし、POSTがそのコンテンツタイプで送信されていても、FirefoxがOPTIONSリクエストを送信したことがわかりました。

私はこれをうまく機能させることができました。それは 'Access-Control-Allow-Origin'レスポンスヘッダを '*'に設定する、サーバ上のオプションリクエストハンドラを作成することです。 ' http://someurl.com 'のように、それを特定のものに設定することでより制限的になることができます。また、私は、おそらく、あなたが複数の起源のコンマ区切りのリストを指定することができると読んだが、私はこれをうまく動かすことができなかった。

Firefoxは、受け入れ可能な 'Access-Control-Allow-Origin'値を指定したOPTIONSリクエストに対する応答を受信すると、POSTリクエストを送信します。

16
Mike C

私は完全にApacheベースのソリューションを使ってこの問題を修正しました。私のvhost/htaccessに、次のブロックを追加しました。

# enable cross domain access control
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS"

# force Apache to return 200 without executing my scripts
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule .* / [R=200,L]

Apacheがターゲットスクリプトを実行したときに何が起こるかによっては、後者の部分は必要ないかもしれません。クレジットは、後半の フレンドリーなServerFaultの人々 に行きます。

15
Mark McDonald

応答するスクリプトの先頭にあるこのPHPは機能しているようです。 (Firefox 3.6.11では、まだ多くのテストを行っていません。)

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
header('Access-Control-Max-Age: 1000');
if(array_key_exists('HTTP_ACCESS_CONTROL_REQUEST_HEADERS', $_SERVER)) {
    header('Access-Control-Allow-Headers: '
           . $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']);
} else {
    header('Access-Control-Allow-Headers: *');
}

if("OPTIONS" == $_SERVER['REQUEST_METHOD']) {
    exit(0);
}
10
Chad Clark

グーグルマップにリクエストを送信するのと同じ問題を抱えていました、そしてjQuery 1.5で解決策は非常に簡単です - dataTypeの使用dataType: "jsonp"

7
Slav

原因はOPTIONSメソッドを使用したプリフライトリクエストです

ユーザデータに副作用を引き起こす可能性があるHTTPリクエストメソッド(特に、GET以外のHTTPメソッド、または特定のMIMEタイプでのPOSTの使用)の場合、仕様ではブラウザがリクエストを "プリフライト"することを要求します。 HTTP OPTIONSリクエストメソッドを使用してサーバーからサポートされているメソッドを要求し、サーバーから "承認"されたら、実際のHTTPリクエストメソッドを使用して実際のリクエストを送信します。

Web仕様は次を参照してください。 https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

私はNginx confに以下の行を追加することで問題を解決しました。

    location / {
               if ($request_method = OPTIONS ) {
                   add_header Access-Control-Allow-Origin  "*";
                   add_header Access-Control-Allow-Methods "POST, GET, PUT, UPDATE, DELETE, OPTIONS";
                   add_header Access-Control-Allow-Headers "Authorization";
                   add_header Access-Control-Allow-Credentials  "true";
                   add_header Content-Length 0;
                   add_header Content-Type text/plain;
                   return 200;
               }
    location ~ ^/(xxxx)$ {
                if ($request_method = OPTIONS) {
                    rewrite ^(.*)$ / last;
                }
    }
6
thinkhy

私はソース1.3.2を見ていました、JSONPを使うとき、要求は動的にSCRIPT要素を構築することによってなされます、そしてそれはブラウザの同じドメイン方針を通り過ぎます。当然、SCRIPT要素を使ってPOSTリクエストを行うことはできません。ブラウザはGETを使って結果を取得します。

JSONP呼び出しを要求しているとき、SCRIPT要素は生成されません。これはAJAX呼び出しのTypeがGETに設定されている場合にのみ行われるためです。

http://dev.jquery.com/ticket/4690

4
Slava0008

私たちはASP.Netでこのような問題を抱えていました。 PageHandlerFactoryによるHTMLコンテンツを取得するためにjQueryの$.postを実行しようとしたときに、IISがInternal Server Errorを返していましたが、GET,HEAD,POST,DEBUG動詞のみを応答するように制限されていました。そのため、リストに動詞 "OPTIONS"を追加するか、または "All Verbs"を選択することで、制限を変更できます。

IIS Managerでそれを変更し、Webサイトを選択してからHandler Mappingsを選択し、必要に応じてPageHandlerFactory for * .apxファイルをダブルクリックします(フレームワーク4.0の統合アプリケーションプールを使用)。 [要求の制限]をクリックして[動詞]タブに移動し、変更内容を適用します。

これで$.postリクエストは期待通りに動作しています:)

3
fboiton

o.url = 'index.php'とこのファイルが存在すれば問題ないと思われ、コンソールに成功のメッセージが返されます。私がurlを使用するならば、それはエラーを返します:http://www.google.com

投稿リクエストを行う場合、なぜ $。post メソッドを直接使用しないのか:

$.post("test.php", { func: "getNameAndTime" },
    function(data){
        alert(data.name); // John
        console.log(data.time); //  2pm
    }, "json");

とても簡単です。

2
Elzo Valugi

フォームのaction URLにドメインのwww部分が含まれているかどうかを確認します。開いた元のページはwwwなしで表示されます。

通常はCanonical Urlsに対して行われます。

私はこの記事を読む前に何時間も苦労し、Cross Domainのヒントを見つけました。

2
Bijay Rungta

問題を回避するためのもう1つの可能性はプロキシスクリプトを使用することです。その方法は の例で説明されています

1
Niehztog

私はあなたがPOSTしているドメインのサーバーコードを制御するならばこれを解決する方法の明確な例を投稿しました。この答えはこのスレッドで触れられていますが、これはより明確にそれをIMOについて説明します。

クロスドメインのPOSTリクエストをJavaScriptで送信するにはどうすればよいですか?

1
rynop

これに対する解決策は以下のとおりです。

  1. dataType:jsonを使用してください
  2. あなたのURLに&callback=?を追加してください

これは、Facebook APIの呼び出しとFirefoxでの作業です。 Firebugは上記の条件(両方とも)でGETの代わりにOPTIONSを使用しています。

1
Antonio Gulli

私はFacebook APIを使用しようとすると同様の問題を抱えていました。

Preflightedリクエストを送信しなかった唯一のcontentTypeは、text/plainだけだったようです…。mozilla で言及されている残りのパラメータではありません

  • これがこれを行う唯一のブラウザなのはなぜですか?
  • Facebookがプリフライトリクエストを認識して受け入れないのはなぜですか。

FYI:前述のMozのドキュメントはX-Loriヘッダがプリフライトリクエストを引き起こすべきであることを示唆しています…そうではありません。

0
Drew

あなたはサーバー側でいくらかの仕事をする必要があります。サーバーサイドでPHPを使用しているようですが、.NET Webアプリケーションの解決策は次のとおりです。 jQuery.ajaxでcontent-typeを 'application/json'に設定できません

PHPスクリプトで同じことをするとうまくいきます。単純に:最初の要求でブラウザはそのようなタイプでそのようなデータを送信することが許可されているかどうかをサーバに尋ねており、2番目の要求は適切/許可されています。

0
Fanda

以下を追加してみてください。

dataType: "json",
ContentType: "application/json",
data: JSON.stringify({"method":"getStates", "program":"EXPLORE"}),  
0
Mary Jain

私はすでにphpで私のcors状況をうまく処理するこのコードを持っています。

header( 'Access-Control-Allow-Origin: '.CMSConfig::ALLOW_DOMAIN );
header( 'Access-Control-Allow-Headers: '.CMSConfig::ALLOW_DOMAIN );
header( 'Access-Control-Allow-Credentials: true' );

そしてそれはローカルでもリモートでも問題なく機能していましたが、リモートでのアップロードでは機能しませんでした。

Apache/php OR私のコードで何かが起きました。OPTIONSを要求したときに検索しなくても302の結果が返されます。そのため、私のブラウザは許容できる状況として認識しません。

@ Mark McDonaldの回答に基づいて私がしたことは、このコードをヘッダーの後に追加することです。

if( $_SERVER['REQUEST_METHOD'] === 'OPTIONS' )
{
    header("HTTP/1.1 202 Accepted");
    exit;
}

今、OPTIONSを要求するとき、それは単にヘッダと202結果を送るでしょう。

0
Ratata Tata

せずにこれを試すことができます

contentType:application/x-www-form-urlencoded

0
Mathias F

オプションを追加してみてください。

dataType: "json"

0
ScottE

別のサーバーでホストされている私のApache solrにデータをポストしたいときに、私はプロキシーURLを使って同様の問題を解決しました。 (これは完璧な答えではないかもしれませんが、それは私の問題を解決します。)

次のURLに従ってください。 プロキシのモード書き換え を使用して、httpd.confに次の行を追加します。

 RewriteRule ^solr/(.*)$ http://ip:8983/solr$1 [P]

そのため、 http:// ip:8983/solr / *にデータを投稿する代わりに、/ solrにデータを投稿するだけです。その後、同じOriginにデータを投稿します。

0
Bernice
 function test_success(page,name,id,divname,str)
{ 
 var dropdownIndex = document.getElementById(name).selectedIndex;
 var dropdownValue = document.getElementById(name)[dropdownIndex].value;
 var params='&'+id+'='+dropdownValue+'&'+str;
 //makerequest_sp(url, params, divid1);

 $.ajax({
    url: page,
    type: "post",
    data: params,
    // callback handler that will be called on success
    success: function(response, textStatus, jqXHR){
        // log a message to the console
        document.getElementById(divname).innerHTML = response;

        var retname = 'n_district';
        var dropdownIndex = document.getElementById(retname).selectedIndex;
        var dropdownValue = document.getElementById(retname)[dropdownIndex].value;
        if(dropdownValue >0)
        {
            //alert(dropdownValue);
            document.getElementById('inputname').value = dropdownValue;
        }
        else
        {
            document.getElementById('inputname').value = "00";
        }
        return;
        url2=page2; 
        var params2 = parrams2+'&';
        makerequest_sp(url2, params2, divid2);

     }
});         
}
0
Naser Gulzade