クロスドメインのPOSTリクエストをJavaScriptで送信する方法
注 - ページを更新してはいけません。後で応答を取得して解析する必要があります。
Update:続行する前に、CORSの html5rocksチュートリアル を読んで理解する必要があります。わかりやすく、非常に明確です。
POSTされるサーバーを制御する場合は、サーバーに応答ヘッダーを設定することにより、「クロスオリジンリソース共有標準」を利用します。この回答は、このスレッドの他の回答で説明されていますが、私の意見ではあまり明確ではありません。
要するに、from.com/1.htmlからto.com/postHere.phpへのクロスドメインPOSTの実現方法です(例としてPHPを使用)。注: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 "。サーバーはそれで問題ないので、ブラウザーは2番目の要求(今回はPOST)を行います。クライアントが送信するコンテンツタイプを設定することをお勧めします。したがって、同様に許可する必要があります。
MDNには HTTPアクセス制御 についての優れた記事があり、フロー全体の仕組みの詳細を説明しています。彼らのドキュメントによると、「クロスサイトXMLHttpRequestをサポートするブラウザで動作する」はずです。ただし、ITHINKは最新のブラウザでのみクロスドメインPOSTが許可されるため、これは少し誤解を招く可能性があります。私はこれがsafari、chrome、FF 3.6でのみ動作することを確認しました。
これを行う場合は、次のことに注意してください。
リモートサーバーを制御する場合は、 この回答で説明されているように、おそらくCORSを使用する必要があります ; IE8以降、およびFF、GC、Safariのすべての最新バージョンでサポートされています。 (ただし、IE8および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
asyncコールバックが呼び出されるため、ページは更新されません。
$.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
}
});
関係するすべてのサーバーにアクセスできる場合は、他のドメインで要求されているページの返信のヘッダーに次のコードを追加してください。
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 =あなたの最初のiframeで "post"に設定し、必要に応じてenctypeを "multipart/form-data"に設定します(あなたが望むのでPOSTをしたいと思います)写真のようなマルチパートデータを送信するには?
準備ができたら、フォームにPOST()を送信させます。
もしあなたが他のドメインがiframeとのクロスドメイン通信を行うjavascriptを返すことができるなら( http://softwareas.com/cross-domain-communication-with-iframes )そしてあなたは運がいいです、そしてあなたは応答もキャプチャできます。
もちろん、サーバーをプロキシとして使用したい場合は、これをすべて回避できます。自分のサーバーにフォームを送信するだけで、他のサーバーに要求が転送され(他のサーバーがIPの不一致に気付くように設定されていないと仮定して)、応答が得られます。
注意すべきもう一つの重要なこと! example の上に使い方の説明があります
$.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環境でこれを実行する場合は、次の手順に従います。(これは this threadで提供されるソリューションの概要です)
"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
}
});
私は最善の方法はXMLHttpRequest(例えばjQueryでは$ .ajax()、$ .post())をCross-Origin Resource Sharing polyfillsの一つと一緒に使うことだと思います https://github.com/Modernizr/Modernizr/wiki/ HTML5-Cross-Browser-Polyfills#wiki-CORS
高レベル………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………).
あなたのページは動的に見えないiframeを作成し、それはother-server.comへのあなたのトランスポートとして機能します。あなたはそれからあなたのページからother-server.comにJSを通して通信しなければならなくて、あなたのページにデータを返すコールバックを持っています。
可能だがyour-server.comとother-server.comからの調整が必要
もう1つの方法があります(html5機能を使用)。他のドメインでホストされているプロキシiframeを使用することができます。そのiframeにpostMessageを使用してメッセージを送信すると、そのiframeはPOST request(同じドメイン上)を実行できます。
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)
}
これは古い質問ですが、いくつかの新しい技術が誰かを助けるかもしれません。
他のサーバーへの管理アクセス権がある場合は、オープンソースの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.');
}
});
YQLカスタムテーブル+ JS XHRで可能になるはずです: http://developer.yahoo.com/yql/guide/index.html
私はそれを使用していくつかのクライアントサイド(js)htmlスクレイピングをします、うまくいきます(私は完全なオーディオプレーヤーを持っています、インターネット/プレイリスト/歌詞/最後のFM情報、すべてのクライアントjs + YQLで検索)
クロスドメインサーバーにアクセスでき、サーバー側でコードを変更したくない場合は、 - 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要求をバイパスします。ライブラリは内部的にクレデンシャルとすべての可能なメソッドで動作するiframeソリューションを使用します:GET、POSTなど.
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)
CORSはあなたのためです。 CORSは「クロスオリジンリソース共有」であり、クロスドメインリクエストを送信する方法です。NowXMLHttpRequest2とFetch APIの両方がCORSをサポートし、POSTとGETリクエストの両方を送信できます。
しかし、それには限界があります。サーバーは Access-Control-Allow-Origin を特別に要求する必要があり、 '*'に設定することはできません。
また、Originからリクエストを送信できるようにするには、JSONPが必要です( Access-Control-Allow-Origin も設定する必要がありますが、「*」にすることもできます)。
あなたが選択の仕方がわからない場合のリクエスト方法の多くのために、私はあなたがそれを行うために完全な機能的なコンポーネントが必要だと思います。私は簡単なコンポーネントを紹介しましょう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、さらにはHTMLの<script>
など、プロジェクトにインポートするためのすべての方法をサポートします。