JavaScript経由でクロスドメインPOSTリクエストを送信するにはどうすればよいですか?
注-ページを更新する必要はありません。後で応答を取得して解析する必要があります。
JavaScript経由でクロスドメインPOSTリクエストを送信するにはどうすればよいですか?
注-ページを更新する必要はありません。後で応答を取得して解析する必要があります。
回答:
更新:続行する前に、CORSのhtml5rocksチュートリアルを読んで理解してください。理解しやすく、非常に明確です。
POSTされるサーバーを制御する場合は、サーバーに応答ヘッダーを設定して、「クロスオリジンリソースシェアリング標準」を活用します。この回答はこのスレッドの他の回答で説明されていますが、私の意見ではあまり明確ではありません。
つまり、from.com / 1.htmlからto.com/postHere.php(例としてPHPを使用)へのクロスドメインPOSTを実行する方法を以下に示します。注:Access-Control-Allow-Origin
NON OPTIONS
リクエストに対してのみ設定する必要があります-この例では、小さいコードスニペットのすべてのヘッダーを常に設定します。
postHere.phpで次のように設定します。
switch ($_SERVER['HTTP_ORIGIN']) {
case 'http://from.com': case 'https://from.com':
header('Access-Control-Allow-Origin: '.$_SERVER['HTTP_ORIGIN']);
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
header('Access-Control-Max-Age: 1000');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
break;
}
これにより、スクリプトでクロスドメインのPOST、GET、およびOPTIONSを実行できます。これは、読み続けるにつれて明らかになります...
JSからクロスドメインPOSTをセットアップします(jQueryの例):
$.ajax({
type: 'POST',
url: 'https://to.com/postHere.php',
crossDomain: true,
data: '{"some":"json"}',
dataType: 'json',
success: function(responseData, textStatus, jqXHR) {
var value = responseData.someKey;
},
error: function (responseData, textStatus, errorThrown) {
alert('POST failed.');
}
});
手順2でPOSTを実行すると、ブラウザは "OPTIONS"メソッドをサーバーに送信します。これは、ブラウザがサーバーをPOSTしていてクールかどうかを確認するための「スニフ」です。サーバーは "Access-Control-Allow-Origin"で応答し、要求が " http://from.com "または " https://from.com " から発信された場合、POST | GET | ORIGINへのOKをブラウザーに通知します。サーバーはそれで問題ないので、ブラウザーは2番目の要求を行います(今回はPOST)。クライアントが送信するコンテンツタイプを設定することをお勧めします。そのため、これも許可する必要があります。
MDNには、HTTPアクセス制御に関する優れた記事があり、フロー全体のしくみについて詳しく説明しています。彼らのドキュメントによれば、「クロスサイトXMLHttpRequestをサポートするブラウザで動作する」はずです。私は、これは、しかし、少し誤解を招くですTHINKだけ現代のブラウザは、クロスドメインのPOSTを可能にします。私はこれがサファリ、クロム、FF 3.6でのみ動作することを確認しました。
この場合、次の点に注意してください。
400 Bad Request
にOPTIONS
要求。そして、でfirefox
の、第2の要求POST
なされることはありません。:(
リモートサーバーを制御している場合は、この回答で説明されているように、おそらくCORSを使用する必要があります。IE8以降、およびFF、GC、Safariの最近のすべてのバージョンでサポートされています。(ただし、IE8とIE 9では、CORSではリクエストでCookieを送信できません。)
したがって、リモートサーバーを制御しない場合、またはIE7をサポートする必要がある場合、またはCookieが必要でIE8 / 9をサポートする必要がある場合は、おそらくiframeテクニックを使用する必要があります。
これがサンプルコードです。IE6、IE7、IE8、IE9、FF4、GC11、S5でテストしました。
function crossDomainPost() {
// Add the iframe with a unique name
var iframe = document.createElement("iframe");
var uniqueString = "CHANGE_THIS_TO_SOME_UNIQUE_STRING";
document.body.appendChild(iframe);
iframe.style.display = "none";
iframe.contentWindow.name = uniqueString;
// construct a form with hidden inputs, targeting the iframe
var form = document.createElement("form");
form.target = uniqueString;
form.action = "http://INSERT_YOUR_URL_HERE";
form.method = "POST";
// repeat for each parameter
var input = document.createElement("input");
input.type = "hidden";
input.name = "INSERT_YOUR_PARAMETER_NAME_HERE";
input.value = "INSERT_YOUR_PARAMETER_VALUE_HERE";
form.appendChild(input);
document.body.appendChild(form);
form.submit();
}
注意してください!iframeは別のドメインに存在するため、POSTの応答を直接読み取ることはできません。フレームは、異なるドメインから相互に通信することはできません。これは同一生成元ポリシーです。
リモートサーバーを制御しているがCORSを使用できない場合(たとえば、IE8 / IE9を使用していて、Cookieを使用する必要がある場合)、次を使用するなどして、同じ生成元のポリシーを回避する方法があります。 window.postMessage
かあります。古いブラウザでクロスドメインクロスフレームメッセージを送信できる多数のライブラリの1つ:
リモートサーバーを制御しないと、POST期間の応答を読み取ることができません。そうしないと、セキュリティ上の問題が発生します。
疑似コード
var ifr = document.createElement('iframe');
var frm = document.createElement('form');
frm.setAttribute("action", "yoururl");
frm.setAttribute("method", "post");
// create hidden inputs, add them
// not shown, but similar (create, setAttribute, appendChild)
ifr.appendChild(frm);
document.body.appendChild(ifr);
frm.submit();
おそらく、iframeのスタイルを設定し、非表示にして絶対配置する必要があります。ブラウザでクロスサイト投稿が許可されるかどうかはわかりませんが、許可されている場合は、これがその方法です。
複雑にしないでおく:
クロスドメインPOST:
使用crossDomain: true,
ページを更新するべきではありません:
としてはありませんが、それはページを更新しませんsuccess
かerror
非同期コールバックがときにサーバーのセンドバック応答と呼ばれます。
$.ajax({
type: "POST",
url: "http://www.yoururl.com/",
crossDomain: true,
data: 'param1=value1¶m2=value2',
success: function (data) {
// do something with server response data
},
error: function (err) {
// handle your error logic here
}
});
crossDomain: true
奇妙なことに、実際のクロスドメイン要求とはまったく関係ありません。リクエストがクロスドメインの場合、jqueryはこれを自動的にtrueに設定します。
関連するすべてのサーバーにアクセスできる場合は、他のドメインで要求されているページの応答のヘッダーに以下を入力します。
PHP:
header('Access-Control-Allow-Origin: *');
たとえば、Drupalのxmlrpc.phpコードでは、次のようにします。
function xmlrpc_server_output($xml) {
$xml = '<?xml version="1.0"?>'."\n". $xml;
header('Connection: close');
header('Content-Length: '. strlen($xml));
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/x-www-form-urlencoded');
header('Date: '. date('r'));
// $xml = str_replace("\n", " ", $xml);
echo $xml;
exit;
}
これはおそらくセキュリティ上の問題を引き起こすので、要求を検証するために適切な手段を講じていることを確認する必要があります。
http://taiyolab.com/mbtweet/scripts/twitterapi_call.jsのpost_method
関数を確認してください-上記のiframeメソッドの良い例です。
2つの非表示のiframeを作成します(CSSスタイルに「display:none;」を追加します)。2番目のiframeを自分のドメイン上の何かに向けます。
非表示フォームを作成し、そのメソッドをtarget = your first iframeで "post"に設定し、オプションでenctypeを "multipart / form-data"に設定します(画像のようなマルチパートデータを送信するため、POSTを実行したいと考えています?)
準備ができたら、フォームsubmit()をPOSTにします。
他のドメインがIframeとのクロスドメイン通信を行うJavaScriptを返すようにできる場合(http://softwareas.com/cross-domain-communication-with-iframes)、運が良ければ、応答をキャプチャできます。同様に。
もちろん、サーバーをプロキシとして使用する場合は、これをすべて回避できます。フォームを独自のサーバーに送信するだけで、要求が他のサーバーにプロキシされ(他のサーバーがIPの不一致に気付くように設定されていない場合)、応答が返され、必要なものが返されます。
注意すべきもう一つの重要なこと!!! では例は使用方法を説明しています上
$.ajax({
type : 'POST',
dataType : 'json',
url : 'another-remote-server',
...
});
JQuery 1.6以下には、クロスドメインXHRのバグがあります。Firebugによると、OPTIONS以外のリクエストは送信されていません。POSTしない。全然。
コードを5時間テスト/調整しました。リモートサーバーに多数のヘッダーを追加する(スクリプト)。影響なし。しかし、後で、JQuery libを1.6.4に更新しました。すべてが魅力のように機能します。
あなたはjQueryのAJAXとASP.net MVC環境でこれを実行したい場合は、次の手順を実行します(これはで提供されるソリューションの概要である。このスレッドで)。
「caller.com」(任意のWebサイトにすることができます)が「server.com」(ASP.net MVCアプリケーション)に投稿する必要があると仮定します。
「server.com」アプリのWeb.configに次のセクションを追加します。
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="POST, GET, OPTIONS" />
</customHeaders>
</httpProtocol>
"server.com"で、投稿先のコントローラー( "Home"と呼ばれます)に対して次のアクションを実行します。
[HttpPost]
public JsonResult Save()
{
//Handle the post data...
return Json(
new
{
IsSuccess = true
});
}
次に、「caller.com」から、次のようにフォーム(html IDが「formId」)から「server.com」にデータを投稿します。
$.ajax({
type: "POST",
url: "http://www.server.com/home/save",
dataType: 'json',
crossDomain: true,
data: $(formId).serialize(),
success: function (jsonResult) {
//do what ever with the reply
},
error: function (jqXHR, textStatus) {
//handle error
}
});
もう1つの方法があります(html5機能を使用)。他のドメインでホストされているプロキシiframeを使用し、postMessageを使用してそのiframeにメッセージを送信すると、そのiframeがPOSTリクエスト(同じドメインで)を実行し、親ウィンドウへの返信でpostMessageを返すことができます。
sender.comの親
var win = $('iframe')[0].contentWindow
function get(event) {
if (event.origin === "http://reciver.com") {
// event.data is response from POST
}
}
if (window.addEventListener){
addEventListener("message", get, false)
} else {
attachEvent("onmessage", get)
}
win.postMessage(JSON.stringify({url: "URL", data: {}}),"http://reciver.com");
reciver.comのiframe
function listener(event) {
if (event.origin === "http://sender.com") {
var data = JSON.parse(event.data);
$.post(data.url, data.data, function(reponse) {
window.parent.postMessage(reponse, "*");
});
}
}
// don't know if we can use jQuery here
if (window.addEventListener){
addEventListener("message", listener, false)
} else {
attachEvent("onmessage", listener)
}
高レベル.... other-serve.your-server.comがother-server.comを指すように、サーバーにcnameを設定する必要があります。
ページは、other-server.comへのトランスポートとして機能する非表示のiframeを動的に作成します。次に、JSを介してページからother-server.comに通信し、データをページに返すコールバックを行う必要があります。
可能ですが、your-server.comおよびother-server.comからの調整が必要です
最善の方法は、クロスオリジンリソースシェアリングポリフィルのいずれかでXMLHttpRequest(たとえば、jQueryの$ .ajax()、$。post())を使用することだと思いますhttps://github.com/Modernizr/Modernizr/wiki/HTML5-クロスブラウザポリフィル#wiki-CORS
これは古い質問ですが、新しいテクノロジーが誰かを助けるかもしれません。
他のサーバーへの管理アクセス権がある場合は、オープンソースのForgeプロジェクトを使用して、クロスドメインPOSTを実行できます。Forgeは、FlashのrawソケットAPIを利用するクロスドメインJavaScript XmlHttpRequestラッパーを提供します。POSTはTLSを介して行うこともできます。
POST先のサーバーへの管理アクセスが必要な理由は、ドメインからのアクセスを許可するクロスドメインポリシーを提供する必要があるためです。
これは古い質問であることは知っていますが、私のアプローチを共有したいと思いました。私はcURLをプロキシとして使用しています。非常に簡単で一貫しています。submit.phpというphpページを作成し、次のコードを追加します。
<?
function post($url, $data) {
$header = array("User-Agent: " . $_SERVER["HTTP_USER_AGENT"], "Content-Type: application/x-www-form-urlencoded");
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
$url = "your cross domain request here";
$data = $_SERVER["QUERY_STRING"];
echo(post($url, $data));
次に、あなたのjsで(ここではjQuery):
$.ajax({
type: 'POST',
url: 'submit.php',
crossDomain: true,
data: '{"some":"json"}',
dataType: 'json',
success: function(responseData, textStatus, jqXHR) {
var value = responseData.someKey;
},
error: function (responseData, textStatus, errorThrown) {
alert('POST failed.');
}
});
CORSはあなたのためです。CORSは「クロスオリジンリソースシェアリング」であり、クロスドメインリクエストを送信する方法です。XMLHttpRequest2とFetch APIの両方がCORSをサポートし、POSTリクエストとGETリクエストの両方を送信できます。
しかし、それには限界があります。サーバーはAccess-Control-Allow-Originを具体的に要求する必要があります、「*」に設定することはできません。
そして、任意のオリジンがリクエストを送信できるようにする場合は、JSONPが必要です(Access-Control-Allow-Originも設定する必要がありますが、「*」にすることもできます)。
選択方法がわからない場合の多くのリクエスト方法では、それを行うには完全な機能コンポーネントが必要だと思います。シンプルなコンポーネントを紹介しましょうhttps://github.com/Joker-Jelly/catta
最新のブラウザー(> IE9、Chrome、FF、Edgeなど)を使用している場合は、シンプルだが美しさのコンポーネントhttps://github.com/Joker-Jelly/cattaを使用することを強くお勧めします。依存関係はありません。 3KB以上で、Fetch、AJAX、JSONPをサポートし、致命的なサンプルの構文とオプションを使用しています。
catta('./data/simple.json').then(function (res) {
console.log(res);
});
また、ES6モジュール、CommonJS <script>
、HTMLのように、プロジェクトにインポートするすべての方法をサポートします。
クロスドメインサーバーにアクセスでき、サーバー側でコードを変更したくない場合は、「xdomain」というライブラリを使用できます。
使い方:
ステップ1:サーバー1:xdomainライブラリーを組み込み、クロスドメインをスレーブとして構成します。
<script src="js/xdomain.min.js" slave="https://crossdomain_server/proxy.html"></script>
ステップ2:クロスドメインサーバーで、proxy.htmlファイルを作成し、サーバー1をマスターとして含めます。
proxy.html:
<!DOCTYPE HTML>
<script src="js/xdomain.min.js"></script>
<script>
xdomain.masters({
"https://server1" : '*'
});
</script>
ステップ3:
これで、server1からのエンドポイントとしてproxy.htmlへのAJAX呼び出しを行うことができます。これはCORS要求をバイパスします。ライブラリは内部的に、資格情報とすべての可能なメソッド(GET、POSTなど)で機能するiframeソリューションを使用します。
ajaxコードのクエリ:
$.ajax({
url: 'https://crossdomain_server/proxy.html',
type: "POST",
data: JSON.stringify(_data),
dataType: "json",
contentType: "application/json; charset=utf-8"
})
.done(_success)
.fail(_failed)