J'ai une machine sur mon réseau local (machineA) qui a deux serveurs Web. Le premier est celui intégré à XBMC (sur le port 8080) et affiche notre bibliothèque. Le second serveur est un script CherryPy python (port 8081) que j'utilise pour déclencher une conversion de fichier à la demande. La conversion de fichier est déclenchée par une demande AJAX POST de la page servie par le serveur XBMC.
demande jQuery Ajax
$.post('http://machineA:8081', {file_url: 'asfd'}, function(d){console.log(d)})
En-tête de demande - OPTIONS
Host: machineA:8081
User-Agent: ... Firefox/4.01
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Origin: http://machineA:8080
Access-Control-Request-Method: POST
Access-Control-Request-Headers: x-requested-with
En-tête de réponse - OPTIONS (STATUS = 200 OK)
Content-Length: 0
Access-Control-Allow-Headers: *
Access-Control-Max-Age: 1728000
Server: CherryPy/3.2.0
Date: Thu, 21 Apr 2011 22:40:29 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Content-Type: text/html;charset=ISO-8859-1
Pour le dépannage, j'ai également émis la même commande $ .post de http://jquery.com . C’est là que je suis perplexe: à partir de jquery.com, la demande de publication fonctionne, une demande OPTIONS est envoyée à la suite d’un POST. Les en-têtes de cette transaction sont ci-dessous;
En-tête de demande - OPTIONS
Host: machineA:8081
User-Agent: ... Firefox/4.01
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Origin: http://jquery.com
Access-Control-Request-Method: POST
En-tête de réponse - OPTIONS (STATUS = 200 OK)
Content-Length: 0
Access-Control-Allow-Headers: *
Access-Control-Max-Age: 1728000
Server: CherryPy/3.2.0
Date: Thu, 21 Apr 2011 22:37:59 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Content-Type: text/html;charset=ISO-8859-1
En-tête de demande - POST
Host: machineA:8081
User-Agent: ... Firefox/4.01
Accept: */*
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://jquery.com/
Content-Length: 12
Origin: http://jquery.com
Pragma: no-cache
Cache-Control: no-cache
En-tête de réponse - POST (STATUS = 200 OK)
Content-Length: 32
Access-Control-Allow-Headers: *
Access-Control-Max-Age: 1728000
Server: CherryPy/3.2.0
Date: Thu, 21 Apr 2011 22:37:59 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Content-Type: application/json
Je ne peux pas comprendre pourquoi la même demande fonctionnerait sur un site mais pas sur l'autre. J'espère que quelqu'un pourra peut-être signaler ce qui me manque. Merci de votre aide!
Je suis finalement tombé sur ce lien " ne requête CORS POST fonctionne à partir de javascript simple, mais pourquoi pas avec jQuery? " qui note que jQuery 1.5.1 ajoute le
Access-Control-Request-Headers: x-requested-with
en-tête de toutes les demandes CORS. jQuery 1.5.2 ne fait pas cela. En outre, selon la même question, définir un en-tête de réponse du serveur de
Access-Control-Allow-Headers: *
ne permet pas à la réponse de continuer. Vous devez vous assurer que l'en-tête de réponse inclut spécifiquement les en-têtes requis. c'est à dire:
Access-Control-Allow-Headers: x-requested-with
DEMANDE:
$.ajax({
url: "http://localhost:8079/students/add/",
type: "POST",
crossDomain: true,
data: JSON.stringify(somejson),
dataType: "json",
success: function (response) {
var resp = JSON.parse(response)
alert(resp.status);
},
error: function (xhr, status) {
alert("error");
}
});
RÉPONSE:
response = HttpResponse(json.dumps('{"status" : "success"}'))
response.__setitem__("Content-type", "application/json")
response.__setitem__("Access-Control-Allow-Origin", "*")
return response
Il m'a fallu du temps pour trouver la solution.
Si votre serveur répond correctement et que la requête pose problème, vous devez ajouter withCredentials: true
à la variable xhrFields
de la requête:
$.ajax({
url: url,
type: method,
// This is the important part
xhrFields: {
withCredentials: true
},
// This is the important part
data: data,
success: function (response) {
// handle the response
},
error: function (xhr, status) {
// handle errors
}
});
Remarque: jQuery> = 1.5.1 est requis
Eh bien, je me suis battu avec ce problème pendant quelques semaines.
Pour ce faire, la méthode la plus simple, la plus conforme et la plus simple consiste à utiliser probablement une API JavaScript de fournisseur qui ne fait pas d'appels via un navigateur et qui peut gérer les demandes d'origine croisée.
Par exemple. API Facebook Facebook et API Google JS.
Si votre fournisseur d'API n'est pas à jour et ne prend pas en charge l'en-tête Cross Origin Resource Origin '*' et n'a pas d'API JS (oui, je parle de vous Yahoo), vous êtes frappé par l'une des trois options suivantes:
Utilisation de jsonp dans vos demandes, qui ajoute une fonction de rappel à votre URL où vous pouvez gérer votre réponse. Attention, cela modifiera l'URL de la requête. Votre serveur d'API doit donc être équipé pour gérer le? Callback = à la fin de l'URL.
Envoyez la demande à votre serveur d'API qui est votre contrôleur et qui se trouve soit dans le même domaine que le client, soit sur lequel le partage de ressources d'origine multiple est activé, à partir duquel vous pouvez envoyer la demande par proxy au serveur API tiers.
Probablement plus utile dans les cas où vous faites OAuth demandes et que vous devez gérer l’interaction de l’utilisateur Haha! window.open('url',"newwindowname",'_blank', 'toolbar=0,location=0,menubar=0')
J'ai résolu mon propre problème lors de l'utilisation de l'API google distance matrix en définissant l'en-tête de ma demande avec Jquery ajax. jetez un oeil ci-dessous.
var settings = {
'cache': false,
'dataType': "jsonp",
"async": true,
"crossDomain": true,
"url": "https://maps.googleapis.com/maps/api/distancematrix/json?units=metric&origins=place_id:"+me.originPlaceId+"&destinations=place_id:"+me.destinationPlaceId+"®ion=ng&units=metric&key=mykey",
"method": "GET",
"headers": {
"accept": "application/json",
"Access-Control-Allow-Origin":"*"
}
}
$.ajax(settings).done(function (response) {
console.log(response);
});
Notez ce que j'ai ajouté aux paramètres
**
"headers": {
"accept": "application/json",
"Access-Control-Allow-Origin":"*"
}
**
J'espère que ça aide.
Utiliser ceci en combinaison avec Laravel a résolu mon problème. Ajoutez simplement cet en-tête à votre demande jQuery Access-Control-Request-Headers: x-requested-with
et assurez-vous que votre réponse côté serveur a cet en-tête défini Access-Control-Allow-Headers: *
.
Pour une raison quelconque, une question sur les demandes GET a été fusionnée avec celle-ci, je vais donc y répondre ici.
Cette fonction simple obtiendra de manière asynchrone une réponse de statut HTTP depuis une page activée par CORS. Si vous l'exécutez, vous verrez que seule une page avec les en-têtes appropriés renvoie un statut 200 si elle est accédée via XMLHttpRequest - que GET ou POST soit utilisé. Rien ne peut être fait du côté client pour contourner ce problème, sauf éventuellement utiliser JSONP si vous avez juste besoin d'un objet JSON.
Les éléments suivants peuvent être facilement modifiés pour obtenir les données contenues dans l'objet xmlHttpRequestObject:
function checkCorsSource(source) {
var xmlHttpRequestObject;
if (window.XMLHttpRequest) {
xmlHttpRequestObject = new XMLHttpRequest();
if (xmlHttpRequestObject != null) {
var sUrl = "";
if (source == "google") {
var sUrl = "https://www.google.com";
} else {
var sUrl = "https://httpbin.org/get";
}
document.getElementById("txt1").innerHTML = "Request Sent...";
xmlHttpRequestObject.open("GET", sUrl, true);
xmlHttpRequestObject.onreadystatechange = function() {
if (xmlHttpRequestObject.readyState == 4 && xmlHttpRequestObject.status == 200) {
document.getElementById("txt1").innerHTML = "200 Response received!";
} else {
document.getElementById("txt1").innerHTML = "200 Response failed!";
}
}
xmlHttpRequestObject.send();
} else {
window.alert("Error creating XmlHttpRequest object. Client is not CORS enabled");
}
}
}
<html>
<head>
<title>Check if page is cors</title>
</head>
<body>
<p>A CORS-enabled source has one of the following HTTP headers:</p>
<ul>
<li>Access-Control-Allow-Headers: *</li>
<li>Access-Control-Allow-Headers: x-requested-with</li>
</ul>
<p>Click a button to see if the page allows CORS</p>
<form name="form1" action="" method="get">
<input type="button" name="btn1" value="Check Google Page" onClick="checkCorsSource('google')">
<input type="button" name="btn1" value="Check Cors Page" onClick="checkCorsSource('cors')">
</form>
<p id="txt1" />
</body>
</html>
J'ai eu exactement le même problème où jquery ajax ne m'avait donné que des problèmes concernant les demandes de poste où obtenir des demandes fonctionnaient bien - j'ai fatigué tout ce qui précède sans résultat. J'avais les bons en-têtes sur mon serveur, etc. Passer de XMLHTTPRequest à la place de jquery a immédiatement résolu mon problème. Peu importe la version de jQuery que j'ai utilisée, cela ne résout pas le problème. Fetch fonctionne également sans problème si vous n'avez pas besoin de la compatibilité du navigateur en amont.
var xhr = new XMLHttpRequest()
xhr.open('POST', 'https://mywebsite.com', true)
xhr.withCredentials = true
xhr.onreadystatechange = function() {
if (xhr.readyState === 2) {// do something}
}
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.send(json)
J'espère que cela aidera tout le monde avec les mêmes problèmes.
Ceci est un résumé de ce qui a fonctionné pour moi:
Définir une nouvelle fonction (_ enveloppé $.ajax
pour simplifier):
jQuery.postCORS = function(url, data, func) {
if(func == undefined) func = function(){};
return $.ajax({
type: 'POST',
url: url,
data: data,
dataType: 'json',
contentType: 'application/x-www-form-urlencoded',
xhrFields: { withCredentials: true },
success: function(res) { func(res) },
error: function() {
func({})
}
});
}
Usage:
$.postCORS("https://example.com/service.json",{ x : 1 },function(obj){
if(obj.ok) {
...
}
});
Fonctionne également avec .done
, .fail
, etc:
$.postCORS("https://example.com/service.json",{ x : 1 }).done(function(obj){
if(obj.ok) {
...
}
}).fail(function(){
alert("Error!");
});
Côté serveur (dans le cas où example.com est hébergé), définissez ces en-têtes (avec quelques exemples de code PHP):
header('Access-Control-Allow-Origin: https://not-example.com');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 604800');
header("Content-type: application/json");
$array = array("ok" => $_POST["x"]);
echo json_encode($array);
C’est le seul moyen que je connaisse pour vraiment POST inter-domaines de JS.
JSONP convertit le POST en GET, qui peut afficher des informations sensibles dans les journaux du serveur.
Si pour certaines raisons, lorsque vous essayez d'ajouter des en-têtes ou de définir une stratégie de contrôle, vous n'obtenez toujours rien, vous pouvez envisager d'utiliser Apache ProxyPass…
Par exemple, dans un <VirtualHost>
qui utilise SSL, ajoutez les deux directives suivantes:
SSLProxyEngine On
ProxyPass /oauth https://remote.tld/oauth
Assurez-vous que les modules Apache suivants sont chargés (chargez-les à l'aide de a2enmod):
Évidemment, vous devrez changer votre URL de requêtes AJAX pour pouvoir utiliser le proxy Apache…