Wie sende ich eine domänenübergreifende POST-Anfrage über JavaScript?
Hinweise - Die Seite sollte nicht aktualisiert werden, und ich muss die Antwort anschließend abrufen und analysieren.
Wie sende ich eine domänenübergreifende POST-Anfrage über JavaScript?
Hinweise - Die Seite sollte nicht aktualisiert werden, und ich muss die Antwort anschließend abrufen und analysieren.
Antworten:
Update: Bevor Sie fortfahren, sollten alle das html5rocks-Tutorial zu CORS lesen und verstehen . Es ist leicht zu verstehen und sehr klar.
Wenn Sie den POST-Server steuern, nutzen Sie einfach den "Standard für die gemeinsame Nutzung von Ressourcen", indem Sie auf dem Server Antwortheader festlegen. Diese Antwort wird in anderen Antworten in diesem Thread diskutiert, aber meiner Meinung nach nicht sehr klar.
Kurz gesagt, hier erfahren Sie, wie Sie den domänenübergreifenden POST von from.com/1.html zu to.com/postHere.php durchführen (am Beispiel von PHP). Hinweis: Sie müssen nur Access-Control-Allow-Origin
NON- OPTIONS
Anforderungen festlegen. In diesem Beispiel werden immer alle Header für ein kleineres Code-Snippet festgelegt.
In postHere.php richten Sie Folgendes ein:
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;
}
Auf diese Weise kann Ihr Skript domänenübergreifende POST, GET und OPTIONEN erstellen. Dies wird deutlich, wenn Sie weiterlesen ...
Richten Sie Ihren domänenübergreifenden POST über JS ein (jQuery-Beispiel):
$.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.');
}
});
Wenn Sie den POST in Schritt 2 ausführen, sendet Ihr Browser eine "OPTIONS" -Methode an den Server. Dies ist ein "Schnüffeln" des Browsers, um zu sehen, ob der Server cool ist, wenn Sie darauf posten. Der Server antwortet mit einem "Access-Control-Allow-Origin", der dem Browser mitteilt, dass POST | GET | ORIGIN in Ordnung ist, wenn die Anfrage von " http://from.com " oder " https://from.com " stammt. Da der Server damit einverstanden ist, stellt der Browser eine zweite Anfrage (diesmal einen POST). Es wird empfohlen, dass Ihr Client den Inhaltstyp festlegt, den er sendet. Daher müssen Sie dies ebenfalls zulassen.
MDN hat eine großartige Beschreibung der HTTP-Zugriffskontrolle , die detailliert beschreibt, wie der gesamte Ablauf funktioniert. Laut ihren Dokumenten sollte es "in Browsern funktionieren, die standortübergreifendes XMLHttpRequest unterstützen". Dies ist jedoch etwas irreführend, da ich denke, dass nur moderne Browser domänenübergreifende POST zulassen. Ich habe nur überprüft, dass dies mit Safari, Chrome, FF 3.6 funktioniert.
Beachten Sie dabei Folgendes:
400 Bad Request
auf OPTIONS
Anfrage. und in firefox
der zweiten Anfrage POST
wird nie gemacht. :(
Wenn Sie den Remote-Server steuern, sollten Sie wahrscheinlich CORS verwenden, wie in dieser Antwort beschrieben . Es wird in IE8 und höher sowie in allen neueren Versionen von FF, GC und Safari unterstützt. (In IE8 und 9 können Sie mit CORS jedoch keine Cookies in der Anfrage senden.)
Wenn Sie also den Remote-Server nicht steuern oder IE7 unterstützen müssen oder wenn Sie Cookies benötigen und IE8 / 9 unterstützen müssen, möchten Sie wahrscheinlich eine Iframe-Technik verwenden.
Hier ist Beispielcode; Ich habe es auf IE6, IE7, IE8, IE9, FF4, GC11, S5 getestet.
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();
}
In acht nehmen! Sie können die Antwort des POST nicht direkt lesen, da der Iframe in einer separaten Domäne vorhanden ist. Frames dürfen nicht aus verschiedenen Domänen miteinander kommunizieren. Dies ist die Richtlinie mit demselben Ursprung .
Wenn Sie den Remote-Server steuern, aber CORS nicht verwenden können (z. B. weil Sie sich in IE8 / IE9 befinden und Cookies verwenden müssen), gibt es Möglichkeiten, die Richtlinie mit demselben Ursprung zu umgehen, z. B. mithilfe von window.postMessage
und / oder Eine von mehreren Bibliotheken, mit denen Sie domänenübergreifende Frame-Nachrichten in älteren Browsern senden können:
Wenn Sie den Remote-Server nicht steuern, können Sie die Antwort des POST-Zeitraums nicht lesen. Andernfalls würde es zu Sicherheitsproblemen kommen.
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();
Sie möchten wahrscheinlich den Iframe stylen, versteckt und absolut positioniert sein. Der Browser ist sich nicht sicher, ob Cross-Site-Postings zulässig sind. In diesem Fall ist dies jedoch die Vorgehensweise.
Halte es einfach:
domänenübergreifender POST:
VerwendencrossDomain: true,
Die Seite sollte nicht aktualisiert werden:
Nein, die Seite wird nicht aktualisiert, da dersuccess
odererror
asynchrone Rückruf aufgerufen wird, wenn der Server die Antwort zurücksendet.
$.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
hat seltsamerweise absolut nichts mit echten domänenübergreifenden Anfragen zu tun. Wenn die Anforderung domänenübergreifend ist, setzt jquery dies automatisch auf true.
Wenn Sie Zugriff auf alle beteiligten Server haben, fügen Sie Folgendes in die Kopfzeile der Antwort für die Seite ein, die in der anderen Domäne angefordert wird:
PHP:
header('Access-Control-Allow-Origin: *');
Im xmlrpc.php-Code von Drupal würden Sie beispielsweise Folgendes tun:
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;
}
Dies führt wahrscheinlich zu einem Sicherheitsproblem, und Sie sollten sicherstellen, dass Sie die entsprechenden Maßnahmen ergreifen, um die Anforderung zu überprüfen.
Überprüfen Sie die post_method
Funktion unter http://taiyolab.com/mbtweet/scripts/twitterapi_call.js - ein gutes Beispiel für die oben beschriebene iframe-Methode.
Erstellen Sie zwei versteckte Iframes (fügen Sie dem CSS-Stil "display: none;" hinzu). Stellen Sie Ihren zweiten Iframe auf etwas in Ihrer eigenen Domain.
Erstellen Sie ein verstecktes Formular, setzen Sie seine Methode auf "post" mit target = Ihrem ersten Iframe und setzen Sie den Enctype optional auf "multipart / form-data" (ich denke, Sie möchten POST ausführen, weil Sie mehrteilige Daten wie Bilder senden möchten ?)
Wenn Sie fertig sind, senden Sie das Formular an den POST ().
Wenn Sie die andere Domain dazu bringen können, Javascript zurückzugeben, das die domänenübergreifende Kommunikation mit Iframes ( http://softwareas.com/cross-domain-communication-with-iframes ) ausführt, haben Sie Glück und können die Antwort erfassen auch.
Wenn Sie Ihren Server als Proxy verwenden möchten, können Sie dies natürlich vermeiden. Senden Sie das Formular einfach an Ihren eigenen Server, der die Anforderung an den anderen Server weiterleitet (vorausgesetzt, der andere Server ist nicht so eingerichtet, dass IP-Diskrepanzen festgestellt werden), erhalten Sie die Antwort und geben Sie zurück, was Sie möchten.
Noch eine wichtige Sache zu beachten !!! Im obigen Beispiel wird die Verwendung beschrieben
$.ajax({
type : 'POST',
dataType : 'json',
url : 'another-remote-server',
...
});
JQuery 1.6 und niedriger hat einen Fehler mit domänenübergreifender XHR. Laut Firebug wurden keine Anfragen außer OPTIONEN gesendet. Keine Post. Überhaupt.
Verbrachte 5 Stunden damit, meinen Code zu testen / zu optimieren. Hinzufügen vieler Header auf dem Remote-Server (Skript). Ohne Wirkung. Aber später habe ich JQuery lib auf 1.6.4 aktualisiert und alles funktioniert wie ein Zauber.
Wenn Sie dies in einer ASP.net MVC-Umgebung mit JQuery AJAX tun möchten, gehen Sie folgendermaßen vor: (Dies ist eine Zusammenfassung der in diesem Thread angebotenen Lösung. )
Angenommen, "caller.com" (kann eine beliebige Website sein) muss auf "server.com" (einer ASP.net MVC-Anwendung) posten.
Fügen Sie in der Web.config der App "server.com" den folgenden Abschnitt hinzu:
<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>
Auf "server.com" haben wir die folgende Aktion auf dem Controller ("Home" genannt), auf dem wir veröffentlichen werden:
[HttpPost]
public JsonResult Save()
{
//Handle the post data...
return Json(
new
{
IsSuccess = true
});
}
Senden Sie dann von "caller.com" Daten aus einem Formular (mit der HTML-ID "formId") wie folgt an "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
}
});
Es gibt noch einen weiteren Weg (mit der HTML5-Funktion). Sie können einen Proxy-Iframe verwenden, der in dieser anderen Domäne gehostet wird. Sie senden eine Nachricht mit postMessage an diesen Iframe. Dieser Iframe kann dann POST-Anforderungen (in derselben Domäne) und postMessage mit Reposnse an das übergeordnete Fenster zurückgeben.
Eltern auf 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");
iframe auf reciver.com
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)
}
High Level .... Sie müssen einen cname-Setup auf Ihrem Server haben, damit other-serve.your-server.com auf other-server.com verweist.
Ihre Seite erstellt dynamisch einen unsichtbaren Iframe, der als Transport zu other-server.com dient. Sie müssen dann über JS von Ihrer Seite zu other-server.com kommunizieren und Rückrufe erhalten, die die Daten an Ihre Seite zurückgeben.
Möglich, erfordert jedoch eine Koordination von your-server.com und other-server.com
Ich denke, der beste Weg ist, XMLHttpRequest (z. B. $ .ajax (), $ .post () in jQuery) mit einer der Polyfills für die gemeinsame Nutzung von Ressourcen zu verwenden. Https://github.com/Modernizr/Modernizr/wiki/HTML5- Browserübergreifende Polyfills # wiki-CORS
Dies ist eine alte Frage, aber eine neue Technologie könnte jemandem helfen.
Wenn Sie Administratorzugriff auf den anderen Server haben, können Sie das OpenSource-Forge-Projekt verwenden, um Ihren domänenübergreifenden POST durchzuführen. Forge bietet einen domänenübergreifenden JavaScript XmlHttpRequest-Wrapper, der die Raw-Socket-API von Flash nutzt. Der POST kann sogar über TLS erfolgen.
Der Grund, warum Sie Administratorzugriff auf den Server benötigen, auf den Sie POSTEN, besteht darin, dass Sie eine domänenübergreifende Richtlinie bereitstellen müssen, die den Zugriff von Ihrer Domäne aus ermöglicht.
Ich weiß, dass dies eine alte Frage ist, aber ich wollte meinen Ansatz teilen. Ich benutze cURL als Proxy, sehr einfach und konsistent. Erstellen Sie eine PHP-Seite mit dem Namen submit.php und fügen Sie den folgenden Code hinzu:
<?
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));
Dann in Ihrem js (jQuery hier):
$.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.');
}
});
Sollte dies mit einer benutzerdefinierten YQL-Tabelle + JS XHR möglich sein, sehen Sie sich Folgendes an: http://developer.yahoo.com/yql/guide/index.html
Ich benutze es, um einige clientseitige (js) HTML-Scraping zu machen, funktioniert gut (ich habe einen vollständigen Audio-Player, mit Suche im Internet / Wiedergabelisten / Texten / letzten FM-Informationen, alle Client-js + YQL)
CORS ist für Sie. CORS ist "Cross Origin Resource Sharing" und eine Möglichkeit zum Senden domänenübergreifender Anforderungen. Jetzt unterstützen sowohl die XMLHttpRequest2- als auch die Fetch-API CORS und können sowohl POST- als auch GET-Anforderungen senden
Aber es hat seine Grenzen. Der Server muss den Access-Control-Allow-Origin spezifisch beanspruchen und kann nicht auf '*' gesetzt werden.
Und wenn Sie möchten, dass ein Ursprung eine Anfrage an Sie senden kann, benötigen Sie JSONP (Sie müssen auch Access-Control-Allow-Origin festlegen , können aber '*' sein).
Wenn Sie nicht wissen, wie Sie eine Auswahl treffen sollen, benötigen Sie wahrscheinlich eine voll funktionsfähige Komponente. Lassen Sie mich eine einfache Komponente https://github.com/Joker-Jelly/catta vorstellen
Wenn Sie einen modernen Browser verwenden (> IE9, Chrome, FF, Edge usw.), empfehlen wir Ihnen, eine einfache, aber schöne Komponente zu verwenden: https://github.com/Joker-Jelly/catta. Es besteht keine Abhängigkeit, weniger als 3 KB, und es unterstützt Fetch, AJAX und JSONP mit der gleichen tödlichen Beispielsyntax und -optionen.
catta('./data/simple.json').then(function (res) {
console.log(res);
});
Es unterstützt auch den gesamten Import in Ihr Projekt, wie ES6-Modul, CommonJS und sogar <script>
in HTML.
Wenn Sie Zugriff auf den domänenübergreifenden Server haben und auf der Serverseite keine Codeänderungen vornehmen möchten, können Sie eine Bibliothek mit dem Namen "xdomain" verwenden.
Wie es funktioniert:
Schritt 1: Server 1: Fügen Sie die xdomain-Bibliothek hinzu und konfigurieren Sie die domänenübergreifende Funktion als Slave:
<script src="js/xdomain.min.js" slave="https://crossdomain_server/proxy.html"></script>
Schritt 2: Erstellen Sie auf einem domänenübergreifenden Server eine proxy.html-Datei und fügen Sie Server 1 als Master hinzu:
proxy.html:
<!DOCTYPE HTML>
<script src="js/xdomain.min.js"></script>
<script>
xdomain.masters({
"https://server1" : '*'
});
</script>
Schritt 3:
Jetzt können Sie von server1 aus einen AJAX-Aufruf an die Datei proxy.html als Endpunkt senden. Dies umgeht die CORS-Anforderung. Die Bibliothek verwendet intern die iframe-Lösung, die mit Anmeldeinformationen und allen möglichen Methoden funktioniert: GET, POST usw.
Ajax-Code abfragen:
$.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)