回答:
同じ生成元ポリシーPOST
の(かなり賢明な)制限のため、別のドメインのサービスに対して非同期にすることはできません。JSON-Pが機能するのは、DOMにタグを挿入することが許可されており、どこにでもタグを付けることができるためです。<script>
もちろん、別のドメインのページを通常のフォームPOSTのアクションにすることもできます。
編集:隠されたsを挿入し、そのプロパティをいじくり回すために多くの努力を惜しまない場合、興味深いハックがいくつかあり<iframe>
ます。
POST
他のドメインとブラウザの両方がサポートしている限り、他のドメインへのリクエストを確実に行うことができますCORS
。しかし、それは完全に本当でPOST
ありJSONP
、互換性はありません。
<script>
、別のドメインを指すタグを挿入することで実装されます。ブラウザでPOSTリクエストを実行する唯一の方法は、HTMLフォームまたはXMLHttpRequestを使用することです。
クロスドメインで大量のデータを送信する必要がある場合。私は通常、2つのステップで呼び出すことができるサービスを作成します。
最初に、クライアントはFORMサブミットを実行します(ポストクロスドメイン)。サービスは、入力をサーバーのセッションに格納します(GUIDをキーとして使用)。(クライアントはGUIDを作成し、それを入力の一部として送信します)
次に、クライアントは、FORMポストで使用したものと同じGUIDを使用するパラメーターとして、通常のスクリプト挿入(JSONP)を実行します。サービスはセッションからの入力を処理し、通常のJSONP形式でデータを返します。この後、セッションは破棄されます。
もちろん、これはあなたがサーバーバックエンドを書くことに依存しています。
XMLHttpRequest
まったく関与すべきではありません。Perの回答は、通常のフォーム送信を使用してPOSTリクエストを作成し、次にスクリプト要素の注入を使用してGETリクエストを作成します。
私はこれが深刻なネクロマンシーであることを知っていますが、私はjQueryを使用してJSONP POSTの実装を投稿すると思いました。
基本的に、受け入れられた回答で示唆されているように、私はIFrameアプローチを使用しています。私が別のことをしているのは、リクエストを送信した後、タイマーを使用してiframeでフォームに到達できる場合は監視しています。フォームにアクセスできない場合は、リクエストが返されたことを意味します。次に、通常のJSONPリクエストを使用して、操作のステータスをクエリしています。
私は誰かがそれが役に立つと思うことを望みます。IE8、Chrome、FireFox、Safariでテスト済み。
function JSONPPostForm(form, postUrl, queryStatusUrl, queryStatusSuccessFunc, queryStatusData)
{
var tmpDiv = $('<div style="display: none;"></div>');
form.parent().append(tmpDiv);
var clonedForm = cloneForm(form);
var iframe = createIFrameWithContent(tmpDiv, clonedForm);
if (postUrl)
clonedForm.attr('action', postUrl);
var postToken = 'JSONPPOST_' + (new Date).getTime();
clonedForm.attr('id', postToken);
clonedForm.append('<input name="JSONPPOSTToken" value="'+postToken+'">');
clonedForm.attr('id', postToken );
clonedForm.submit();
var timerId;
var watchIFrameRedirectHelper = function()
{
if (watchIFrameRedirect(iframe, postToken ))
{
clearInterval(timerId);
tmpDiv.remove();
$.ajax({
url: queryStatusUrl,
data: queryStatusData,
dataType: "jsonp",
type: "GET",
success: queryStatusSuccessFunc
});
}
}
if (queryStatusUrl && queryStatusSuccessFunc)
timerId = setInterval(watchIFrameRedirectHelper, 200);
}
function createIFrameWithContent(parent, content)
{
var iframe = $('<iframe></iframe>');
parent.append(iframe);
if (!iframe.contents().find('body').length)
{
//For certain IE versions that do not create document content...
var doc = iframe.contents().get()[0];
doc.open();
doc.close();
}
iframe.contents().find('body').append(content);
return iframe;
}
function watchIFrameRedirect(iframe, formId)
{
try
{
if (iframe.contents().find('form[id="' + formId + '"]').length)
return false;
else
return true;
}
catch (err)
{
return true;
}
return false;
}
//This one clones only form, without other HTML markup
function cloneForm(form)
{
var clonedForm = $('<form></form>');
//Copy form attributes
$.each(form.get()[0].attributes, function(i, attr)
{
clonedForm.attr(attr.name, attr.value);
});
form.find('input, select, textarea').each(function()
{
clonedForm.append($(this).clone());
});
return clonedForm;
}
通常、JSONPは<script>
、JSONPサービスのURLが「src」になるように、呼び出し元のドキュメントにタグを追加することで実装されます。ブラウザは、HTTP GETトランザクションでスクリプトソースをフェッチします。
JSONPサービスが呼び出しページと同じドメインにある場合、おそらく単純な$.ajax()
呼び出しで何かをまとめることができます。それが同じドメインにない場合、それがどのように可能になるかはわかりません。
CORS
場合は、ブラウザもサポートしている限り可能です。これらのケースJSON
では、ではなくプレーンを使用しますJSONP
。
私が何度もやった(ハック)ソリューションがあります。JsonPで投稿できます。(GETで使用できるよりも2000文字を超えるフォームを投稿できます)
クライアントアプリケーションJavaScript
$.ajax({
type: "POST", // you request will be a post request
data: postData, // javascript object with all my params
url: COMAPIURL, // my backoffice comunication api url
dataType: "jsonp", // datatype can be json or jsonp
success: function(result){
console.dir(result);
}
});
JAVA:
response.addHeader( "Access-Control-Allow-Origin", "*" ); // open your api to any client
response.addHeader( "Access-Control-Allow-Methods", "POST" ); // a allow post
response.addHeader( "Access-Control-Max-Age", "1000" ); // time from request to response before timeout
PHP:
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Max-Age: 1000');
このようにして、サーバーを任意のPOSTリクエストに対して開きます。IDまたは何か他のものを提供することにより、これを再度保護する必要があります。
この方法では、リクエストタイプをjsonpからjsonに変更することもできます。どちらも機能し、適切なレスポンスコンテンツタイプを設定するだけです。
jsonp
response.setContentType( "text/javascript; charset=utf-8" );
json
response.setContentType( "application/json; charset=utf-8" );
あなたがサーバーであることはもはやSOP(同じ発信元ポリシー)を尊重しないことに注意してください。
<script>
タグをHTML DOMに挿入するだけでなく、JSONとJSONPの両方のデータ表記を使用できます(たとえば、同じアプリに複数のJSONリクエストを作成し、関数名を使用したい場合は、デスクトップアプリでそれらを使用することもできます)たとえば、リクエスト追跡IDとして)。
可能です、これが私の解決策です:
あなたのjavascriptで:
jQuery.post("url.php",data).complete(function(data) {
eval(data.responseText.trim());
});
function handleRequest(data){
....
}
あなたのurl.phpで:
echo "handleRequest(".$responseData.")";