JavaScriptler arası bir etki alanları arası POST isteğini nasıl gönderirim?
Notlar - sayfayı yenilememeli ve daha sonra yanıtı almam ve ayrıştırmam gerekiyor.
JavaScriptler arası bir etki alanları arası POST isteğini nasıl gönderirim?
Notlar - sayfayı yenilememeli ve daha sonra yanıtı almam ve ayrıştırmam gerekiyor.
Yanıtlar:
Güncelleme: Devam etmeden önce herkes CORS üzerindeki html5rocks eğitimini okumalı ve anlamalıdır . Anlaması kolay ve çok açık.
Gönderilen sunucuyu kontrol ederseniz, sunucuda yanıt üstbilgileri ayarlayarak "Kaynaklar Arası Kaynak Paylaşımı standardı" ndan yararlanmanız yeterlidir. Bu cevap, bu konudaki diğer cevaplarda tartışılmıştır, ancak bence çok net değildir.
Kısacası, etki alanı POST'sini.com/1.html'den.com/postHere.php'ye (örnek olarak PHP kullanarak) nasıl gerçekleştireceğiniz aşağıda açıklanmıştır. Not: yalnızca Access-Control-Allow-Origin
NON OPTIONS
istekleri için ayarlamanız gerekir - bu örnek her zaman daha küçük bir kod snippet'inin tüm üstbilgilerini ayarlar.
PostHere.php kurulumunda aşağıdakileri yapın:
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;
}
Bu, komut dosyanızın etki alanları arası POST, GET ve OPTIONS yapmasını sağlar. Siz okumaya devam ederken bu netleşecek ...
Web alanları arası POST'nizi JS'den ayarlayın (jQuery örneği):
$.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. adımda POST yaptığınızda, tarayıcınız sunucuya bir "OPTIONS" yöntemi gönderir. Bu sunucu tarafından POSTing ile serin olup olmadığını görmek için tarayıcı tarafından bir "sniff" dir. Sunucu, " http://from.com " veya " https://from.com " adresinden gelen istekte tarayıcıya OK-POST | GET | ORIGIN'e uygun olduğunu bildiren bir "Erişim-Denetim-İzin Verme Kökenli" yanıtını verir . Sunucu onunla iyi olduğundan, tarayıcı 2. bir istekte bulunur (bu sefer POST). Müşterinizin gönderdiği içerik türünü ayarlaması iyi bir uygulamadır - bu nedenle buna da izin vermeniz gerekir.
MDN, HTTP erişim kontrolü hakkında , tüm akışın nasıl çalıştığına dair ayrıntılı bir yazıya sahiptir . Dokümanlarına göre, "siteler arası XMLHttpRequest'i destekleyen tarayıcılarda çalışmalıdır". Ancak, sadece modern tarayıcılar etki alanları arası POST'a izin verdiğini düşündüğüm için bu biraz yanıltıcıdır . Ben sadece safari, krom, FF 3.6 ile çalıştığını doğruladım.
Bunu yaparsanız aşağıdakileri unutmayın:
400 Bad Request
de OPTIONS
istek üzerine olsun . ve firefox
ikinci talebinde POST
asla yapılmaz. :(
Uzak sunucuyu kontrol ederseniz, muhtemelen bu cevapta açıklandığı gibi CORS kullanmalısınız ; IE8 ve üzeri sürümlerde ve FF, GC ve Safari'nin tüm son sürümlerinde desteklenir. (Ancak IE8 ve 9'da, CORS istekte çerez göndermenize izin vermez.)
Bu nedenle, uzak sunucuyu kontrol etmezseniz veya IE7'yi desteklemeniz gerekiyorsa veya çerezlere ihtiyacınız varsa ve IE8 / 9'u desteklemeniz gerekiyorsa, muhtemelen bir iframe tekniği kullanmak isteyeceksiniz.
İşte örnek kod; IE6, IE7, IE8, IE9, FF4, GC11, S5 üzerinde test ettim.
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();
}
Dikkat! İframe ayrı bir etki alanında bulunduğundan POST yanıtını doğrudan okuyamazsınız. Çerçevelerin farklı alanlardan birbirleriyle iletişim kurmasına izin verilmez; bu aynı köken politikadır .
Uzak sunucuyu kontrol ediyorsanız ancak CORS kullanamıyorsanız (örneğin, IE8 / IE9'da olduğunuz ve çerezleri kullanmanız gerektiği için), aynı köken politikası etrafında, örneğin window.postMessage
ve / veya eski tarayıcılarda alanlar arası çapraz çerçeve iletileri göndermenizi sağlayan birkaç kitaplıktan biri:
Uzak sunucuyu kontrol etmezseniz, POST döneminin yanıtını okuyamazsınız. Aksi takdirde güvenlik sorunlarına neden olur.
pseudocode
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();
Muhtemelen iframe'i biçimlendirmek, gizli ve kesinlikle konumlandırılmış olmak istersiniz. Siteler arası gönderiye tarayıcı tarafından izin verileceğinden emin değilim, ancak öyleyse bu nasıl yapılır.
Basit tutun:
web alanları arası POST:
kullanımcrossDomain: true,
sayfayı yenilememelidir:
Hayır, sunucu yanıtı geri gönderdiğinde success
veya zaman error
uyumsuz geri çağrı çağırılacağı için sayfayı yenilemez .
$.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
garip bir şekilde gerçek etki alanları arası istekleri ile hiçbir ilgisi yoktur. İstek etki alanları arasındaysa, jquery bunu otomatik olarak true olarak ayarlar.
İlgili tüm sunuculara erişiminiz varsa, diğer etki alanında istenen sayfanın yanıtının başlığına aşağıdakileri ekleyin:
PHP:
header('Access-Control-Allow-Origin: *');
Örneğin, Drupal'ın xmlrpc.php kodunda bunu yaparsınız:
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;
}
Bu muhtemelen bir güvenlik sorunu yaratır ve isteği doğrulamak için uygun önlemleri aldığınızdan emin olmalısınız.
Yukarıda açıklanan iframe yöntemi için iyi bir örnek post_method
olan http://taiyolab.com/mbtweet/scripts/twitterapi_call.js adresindeki işlevi kontrol edin .
İki gizli iframe oluşturun (css stiline "display: none;" ekleyin). İkinci iframe'inizi kendi alan adınızdaki bir şeye yönlendirin.
Gizli bir form oluşturun, yöntemini hedef = ilk iframe'inizle "yayınla" olarak ayarlayın ve isteğe bağlı olarak "çok parçalı / form verisi" için şifreleme ayarlayın (Resimler gibi çok parçalı veriler göndermek istediğiniz için POST yapmak istediğinizi düşünüyorum ?)
Hazır olduğunda, formu POST'a gönder ().
Diğer alanın Iframe'lerle Web Alanları Arası İletişim ( http://softwareas.com/cross-domain-communication-with-iframes ) yapacak javascript'i döndürmesini sağlayabilirsiniz, o zaman şansınız olur ve yanıtı yakalayabilirsiniz de.
Elbette, sunucunuzu proxy olarak kullanmak istiyorsanız, tüm bunlardan kaçınabilirsiniz. Formu kendi sunucunuza gönderin; bu istek, diğer sunucuya proxy gönderir (diğer sunucunun IP tutarsızlıklarını fark edecek şekilde ayarlanmadığı varsayılarak), yanıtı alın ve istediğinizi geri gönderin.
Unutulmaması gereken bir şey daha var !!! Gelen Örneğin o nasıl kullanılacağını tarif ediyor yukarıdaki
$.ajax({
type : 'POST',
dataType : 'json',
url : 'another-remote-server',
...
});
JQuery 1.6 ve önceki sürümler, etki alanları arası XHR ile ilgili bir hataya sahiptir. Firebug'a göre SEÇENEKLER dışında hiçbir istek gönderilmedi. POST yok. Hiç.
Kodumu test etmek / ayarlamak için 5 saat geçirdim. Uzak sunucuya çok sayıda başlık ekleme (script). Herhangi bir etkisi olmadan. Ama daha sonra, JQuery lib'i 1.6.4'e güncelledim ve her şey bir cazibe gibi çalışıyor.
Bunu JQuery AJAX ile ASP.net MVC ortamında yapmak istiyorsanız, şu adımları izleyin: (Bu, bu iş parçacığında sunulan çözümün bir özetidir )
"Caller.com" un (herhangi bir web sitesi olabilir) "server.com" a (ASP.net MVC uygulaması) posta göndermesi gerektiğini varsayalım
"Server.com" uygulamasının Web.config dosyasına aşağıdaki bölümü ekleyin:
<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" da, göndereceğimiz denetleyici ("Ev" olarak adlandırılır) üzerinde aşağıdaki işlemi yapacağız:
[HttpPost]
public JsonResult Save()
{
//Handle the post data...
return Json(
new
{
IsSuccess = true
});
}
Sonra "caller.com" dan, bir formdaki verileri (html id "formId" ile) "server.com" a aşağıdaki gibi gönderin:
$.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
}
});
Bir yol daha var (html5 özelliğini kullanarak). Bu diğer etki alanında barındırılan proxy iframe'i kullanabilirsiniz, bu iframe'e postMessage kullanarak mesaj gönderirsiniz, daha sonra bu iframe ana pencereye reposnse ile POST isteği (ve aynı etki alanında) yapabilir.
sender.com sitesindeki ebeveyn
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'da 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)
}
Yüksek seviye .... other-serve.your-server.com 'un other-server.com' u göstermesi için sunucunuzda bir cname ayarınızın olması gerekir.
Sayfanız, other-server.com sitesine aktarım işlevi gören görünmez bir iframe oluşturur. Daha sonra JS aracılığıyla sayfanızdan other-server.com'a iletişim kurmanız ve verileri sayfanıza geri döndüren geri aramalara sahip olmanız gerekir.
Mümkün ancak your-server.com ve other-server.com'dan koordinasyon gerektirir
En iyi yolu XMLHttpRequest (örn. $ .Ajax (), $ .post () jQuery) Cross-Origin Resource Sharing polyfills ile kullanmaktır https://github.com/Modernizr/Modernizr/wiki/HTML5- Çapraz Tarayıcı Polyfills # wiki CORS
Bu eski bir soru, ancak bazı yeni teknolojiler birine yardım edebilir.
Diğer sunucuya yönetici erişiminiz varsa, etki alanları arası POST'nizi gerçekleştirmek için openource Forge projesini kullanabilirsiniz. Forge, Flash'ın ham soket API'sından yararlanan bir etki alanları arası JavaScript XmlHttpRequest sarmalayıcısı sağlar. POST, TLS üzerinden bile yapılabilir.
POST yapmakta olduğunuz sunucuya yönetici erişimine ihtiyacınızın nedeni, alan adınızdan erişime izin veren bir etki alanları arası politika sağlamanız gerektiğidir.
Bunun eski bir soru olduğunu biliyorum, ama yaklaşımımı paylaşmak istedim. Çok kolay ve tutarlı bir vekil olarak cURL kullanıyorum. Submit.php adlı bir php sayfası oluşturun ve aşağıdaki kodu ekleyin:
<?
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));
Sonra, js (burada 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 özel tablosu + JS XHR ile mümkün olmalı, http://developer.yahoo.com/yql/guide/index.html
Bazı istemci tarafı (js) html kazıma yapmak için kullanıyorum, iyi çalışıyor (internet / çalma listeleri / şarkı sözleri / son fm bilgileri, tüm istemci js + YQL üzerinde arama ile tam bir ses çalarım var)
CORS tam size göre. CORS, "Çapraz Kaynak Kaynağı Paylaşımı" dır, çapraz etki alanı isteği göndermenin bir yoludur.
Ancak sınırları vardır.Sunucunun Access-Control-Allow-Origin için özel talepte bulunması gerekir ve '*' olarak ayarlanamaz.
Ve herhangi bir menşein size istek gönderebilmesini istiyorsanız, JSONP'ye ihtiyacınız var (ayrıca Erişim-Kontrol-İzin Ver-Kökeni , ancak '*' olabilir)
Seçim yolunu bilmiyorsanız birçok istek yolu için, bunu yapmak için tam bir işlevsel bileşene ihtiyacınız olduğunu düşünüyorum. https://github.com/Joker-Jelly/catta
Modern tarayıcı kullanıyorsanız (> IE9, Chrome, FF, Edge, vb.), Çok basit ama güzel bir bileşen kullanmanızı öneririz https://github.com/Joker-Jelly/catta . Bağımlılığı yok, Daha az 3KB'den daha fazladır ve aynı ölümcül örnek sözdizimi ve seçeneklerle Fetch, AJAX ve JSONP'yi destekler.
catta('./data/simple.json').then(function (res) {
console.log(res);
});
Ayrıca ES6 modülü, CommonJS ve hatta <script>
HTML gibi projenize içe aktarmanın tüm yollarını destekler .
Web alanları arası sunucuya erişiminiz varsa ve sunucu tarafında herhangi bir kod değişikliği yapmak istemiyorsanız - 'xdomain' adlı bir kitaplık kullanabilirsiniz.
Nasıl çalışır:
Adım 1: Sunucu 1: xdomain kütüphanesini ekleyin ve çapraz etki alanını bağımlı olarak yapılandırın:
<script src="js/xdomain.min.js" slave="https://crossdomain_server/proxy.html"></script>
2.Adım: Web alanları arası sunucuda bir proxy.html dosyası oluşturun ve sunucu 1'i bir ana sunucu olarak ekleyin:
proxy.html:
<!DOCTYPE HTML>
<script src="js/xdomain.min.js"></script>
<script>
xdomain.masters({
"https://server1" : '*'
});
</script>
Aşama 3:
Artık proxy1html'ye sunucu1'den bitiş noktası olarak AJAX çağrısı yapabilirsiniz. Bu CORS isteğini atlar. Kütüphane, Kimlik Bilgileri ve olası tüm yöntemlerle çalışan iframe çözümünü kullanır: GET, POST vb.
Sorgu ajax kodu:
$.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)