比較的単純な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の出力の図です。
エラーの原因は同じOriginポリシーです。それはあなたがあなた自身のドメインにXMLHTTPRequestsをすることを可能にするだけです。代わりに JSONP コールバックを使用できるかどうかを確認してください。
$.getJSON( 'http://<url>/api.php?callback=?', function ( data ) { alert ( data ); } );
私は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に渡しません。
この mozillaデベロッパーセンターの記事 はクロスドメインリクエストのさまざまなシナリオについて説明しています。この記事は、コンテンツタイプが 'application/x-www-form-urlencoded'のPOST要求は、(単純な要求ではなく)単純な要求として送信する必要があることを示しているようです。ただし、POSTがそのコンテンツタイプで送信されていても、FirefoxがOPTIONSリクエストを送信したことがわかりました。
私はこれをうまく機能させることができました。それは 'Access-Control-Allow-Origin'レスポンスヘッダを '*'に設定する、サーバ上のオプションリクエストハンドラを作成することです。 ' http://someurl.com 'のように、それを特定のものに設定することでより制限的になることができます。また、私は、おそらく、あなたが複数の起源のコンマ区切りのリストを指定することができると読んだが、私はこれをうまく動かすことができなかった。
Firefoxは、受け入れ可能な 'Access-Control-Allow-Origin'値を指定したOPTIONSリクエストに対する応答を受信すると、POSTリクエストを送信します。
私は完全に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の人々 に行きます。
応答するスクリプトの先頭にあるこの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);
}
グーグルマップにリクエストを送信するのと同じ問題を抱えていました、そしてjQuery 1.5で解決策は非常に簡単です - dataTypeの使用dataType: "jsonp"
原因は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;
}
}
私はソース1.3.2を見ていました、JSONPを使うとき、要求は動的にSCRIPT要素を構築することによってなされます、そしてそれはブラウザの同じドメイン方針を通り過ぎます。当然、SCRIPT要素を使ってPOSTリクエストを行うことはできません。ブラウザはGETを使って結果を取得します。
JSONP呼び出しを要求しているとき、SCRIPT要素は生成されません。これはAJAX呼び出しのTypeがGETに設定されている場合にのみ行われるためです。
私たちは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
リクエストは期待通りに動作しています:)
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");
とても簡単です。
フォームのaction
URLにドメインのwww
部分が含まれているかどうかを確認します。開いた元のページはwww
なしで表示されます。
通常はCanonical Urlsに対して行われます。
私はこの記事を読む前に何時間も苦労し、Cross Domainのヒントを見つけました。
問題を回避するためのもう1つの可能性はプロキシスクリプトを使用することです。その方法は の例で説明されています
私はあなたがPOSTしているドメインのサーバーコードを制御するならばこれを解決する方法の明確な例を投稿しました。この答えはこのスレッドで触れられていますが、これはより明確にそれをIMOについて説明します。
これに対する解決策は以下のとおりです。
json
を使用してください&callback=?
を追加してくださいこれは、Facebook APIの呼び出しとFirefoxでの作業です。 Firebugは上記の条件(両方とも)でGET
の代わりにOPTIONS
を使用しています。
私はFacebook APIを使用しようとすると同様の問題を抱えていました。
Preflightedリクエストを送信しなかった唯一のcontentTypeは、text/plainだけだったようです…。mozilla で言及されている残りのパラメータではありません
FYI:前述のMozのドキュメントはX-Loriヘッダがプリフライトリクエストを引き起こすべきであることを示唆しています…そうではありません。
あなたはサーバー側でいくらかの仕事をする必要があります。サーバーサイドでPHPを使用しているようですが、.NET Webアプリケーションの解決策は次のとおりです。 jQuery.ajaxでcontent-typeを 'application/json'に設定できません
PHPスクリプトで同じことをするとうまくいきます。単純に:最初の要求でブラウザはそのようなタイプでそのようなデータを送信することが許可されているかどうかをサーバに尋ねており、2番目の要求は適切/許可されています。
以下を追加してみてください。
dataType: "json",
ContentType: "application/json",
data: JSON.stringify({"method":"getStates", "program":"EXPLORE"}),
私はすでに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結果を送るでしょう。
せずにこれを試すことができます
contentType:application/x-www-form-urlencoded
オプションを追加してみてください。
dataType: "json"
別のサーバーでホストされている私のApache solrにデータをポストしたいときに、私はプロキシーURLを使って同様の問題を解決しました。 (これは完璧な答えではないかもしれませんが、それは私の問題を解決します。)
次のURLに従ってください。 プロキシのモード書き換え を使用して、httpd.confに次の行を追加します。
RewriteRule ^solr/(.*)$ http://ip:8983/solr$1 [P]
そのため、 http:// ip:8983/solr / *にデータを投稿する代わりに、/ solrにデータを投稿するだけです。その後、同じOriginにデータを投稿します。
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);
}
});
}