jQuery $.Ajax.$ ,)(post sending "OPTIONS" comme méthode de requête dans Firefox
ayant des problèmes avec ce que je pensais être un plugin jQuery relativement simple...
le plugin doit récupérer les données d'un script php via ajax pour ajouter des options à un <select>
. La requête ajax est assez générique:
$.ajax({
url: o.url,
type: 'post',
contentType: "application/x-www-form-urlencoded",
data: '{"method":"getStates", "program":"EXPLORE"}',
success: function (data, status) {
console.log("Success!!");
console.log(data);
console.log(status);
},
error: function (xhr, desc, err) {
console.log(xhr);
console.log("Desc: " + desc + "nErr:" + err);
}
});
cela semble bien fonctionner en Safari. Dans Firefox 3.5, REQUEST_TYPE
sur le serveur est toujours "OPTIONS", et les données $_POST n'apparaissent pas. Apache enregistre la requête en tapant 'OPTIONS':
::1 - - [08/Jul/2009:11:43:27 -0500] "OPTIONS sitecodes.php HTTP/1.1" 200 46
pourquoi cet appel ajax fonctionnerait-il en Safari, mais pas en Firefox, et comment puis-je le réparer pour Firefox?
Response Headers Date: Wed, 08 Jul 2009 21:22:17 GMT Server:Apache/2.0.59 (Unix) PHP/5.2.6 DAV/2 X-Powered-By: PHP/5.2.6 Content-Length 46 Keep-Alive timeout=15, max=100 Connection Keep-Alive Content-Type text/html Request Headers Host orderform:8888 User-Agent Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1) Gecko/20090624 Firefox/3.5 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 300 Connection keep-alive Origin http://ux.inetu.act.org Access-Control-Request-Method POST Access-Control-Request-Headers x-requested-with
Voici une image de la sortie Firebug:
23 réponses
La raison de l'erreur est la même origine. Il vous permet seulement de faire des requêtes XMLHTTP à votre propre domaine. Voir si vous pouvez utiliser un JSONP callback à la place:
$.getJSON( 'http://<url>/api.php?callback=?', function ( data ) { alert ( data ); } );
j'ai utilisé le code suivant du côté de Django pour interpréter la requête D'OPTIONS et pour régler les en-têtes de contrôle d'accès nécessaires. Après cela, mes requêtes de domaine croisées de Firefox ont commencé à fonctionner. Comme dit avant, le navigateur envoie d'abord la demande D'OPTIONS et puis immédiatement après que le POST/GET
def send_data(request):
if request.method == "OPTIONS":
response = HttpResponse()
response['Access-Control-Allow-Origin'] = '*'
response['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
response['Access-Control-Max-Age'] = 1000
# note that '*' is not valid for Access-Control-Allow-Headers
response['Access-Control-Allow-Headers'] = 'origin, x-csrftoken, content-type, accept'
return response
if request.method == "POST":
# ...
éditer: il semble qu'au moins dans certains cas, vous devez également ajouter les mêmes en-têtes de contrôle d'accès à la réponse réelle. Cela peut être un peu un peu confus, puisque la requête semble réussir, mais Firefox ne transmet pas le contenu de la réponse au Javascript.
Ce mozilla developer center article décrit les différentes croix-demande de domaine scénarios. L'article semble indiquer qu'une requête POST avec le type de contenu 'application/x-www-form-urlencoded' devrait être envoyée comme une 'requête simple' (Sans option 'preflight'). J'ai trouvé , cependant, que Firefox a envoyé la demande D'OPTIONS, même si mon message a été envoyé avec ce type de contenu.
j'ai pu faire ce travail en créant un options request handler sur le serveur, qui définit l'en-tête de réponse' Access-Control-Allow-Origin 'à'*'. Vous pouvez être plus restrictif en le mettant à quelque chose de spécifique, comme ' http://someurl.com " Aussi, j'ai lu que, soi-disant, Vous pouvez spécifier une liste de plusieurs origines séparées par des virgules, Mais je n'ai pas pu faire que cela fonctionne.
une fois que Firefox reçoit la réponse à la demande D'OPTIONS avec une valeur acceptable "Access-Control-Allow-Origin", il envoie la requête POST.
j'ai corrigé ce problème en utilisant une solution entièrement basée sur Apache. Dans mon vhost / htaccess j'ai mis le bloc suivant:
# enable cross domain access control
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS"
# force apache to return 200 without executing my scripts
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule .* / [R=200,L]
il se peut que vous n'ayez pas besoin de cette dernière partie, selon ce qui se passe quand Apache exécute votre script cible. Le crédit va au serverfault Folk amical pour la dernière partie.
ce PHP en haut du script de réponse semble fonctionner. (Avec Firefox 3.6.11. Je n'ai pas encore fait beaucoup de tests.)
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
header('Access-Control-Max-Age: 1000');
if(array_key_exists('HTTP_ACCESS_CONTROL_REQUEST_HEADERS', $_SERVER)) {
header('Access-Control-Allow-Headers: '
. $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']);
} else {
header('Access-Control-Allow-Headers: *');
}
if("OPTIONS" == $_SERVER['REQUEST_METHOD']) {
exit(0);
}
j'ai eu le même problème avec l'envoi de demandes à google maps, et la solution est assez simple avec jQuery 1.5 - Pour l'utilisation de type de données dataType: "jsonp"
coupable est une demande avant le vol en utilisant la méthode des OPTIONS
pour les méthodes de requête HTTP qui peuvent causer des effets secondaires sur les données de l'utilisateur( en particulier, pour les méthodes HTTP autres que GET, ou pour la POST-utilisation avec certains types MIME), la spécification prescrit que les navigateurs "préviennent" la requête, sollicitant les méthodes prises en charge par le serveur avec une méthode de requête D'OPTIONS HTTP, puis, sur "approbation" du serveur, en envoyant la requête réelle avec la requête HTTP réelle méthode.
Web spécification de se référer à: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
j'ai résolu le problème en ajoutant les lignes suivantes dans nginx conf.
location / {
if ($request_method = OPTIONS ) {
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Methods "POST, GET, PUT, UPDATE, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "Authorization";
add_header Access-Control-Allow-Credentials "true";
add_header Content-Length 0;
add_header Content-Type text/plain;
return 200;
}
location ~ ^/(xxxx)$ {
if ($request_method = OPTIONS) {
rewrite ^(.*)$ / last;
}
}
je regardais à travers la source 1.3.2, en utilisant JSONP, la demande est faite en construisant un élément de SCRIPT dynamiquement, qui passe les navigateurs même-Politique de domaine. Naturellement, vous ne pouvez pas faire une requête POST en utilisant un élément SCRIPT, le navigateur récupérerait le résultat en utilisant GET.
comme vous demandez un appel JSONP, L'élément SCRIPT n'est pas généré, car il ne le fait que lorsque le Type D'appel AJAX est défini pour obtenir.
nous avons eu un problème comme celui-ci avec ASP.Net. Notre IIS retournait une erreur de serveur interne en essayant d'exécuter un jQuery $.post
pour obtenir du contenu html dû à PageHandlerFactory était limité à répondre seulement GET,HEAD,POST,DEBUG
verbes. Vous pouvez donc modifier cette restriction en ajoutant le verbe "OPTIONS" à la liste ou en sélectionnant" Tous les verbes "
vous pouvez modifier cela dans votre IIS Manager, en sélectionnant votre site web, puis en sélectionnant Handler Mappings, double-cliquez dans votre PageHandlerFactory for *.fichiers apx selon vos besoins (nous utilisons le pool d'applications intégré avec framework 4.0). Cliquez sur Request Restrictions, puis allez à Verbs Tabn et appliquez votre modification.
maintenant notre demande $.post
fonctionne comme prévu :)
vérifiez si L'URL action
de votre formulaire inclut la partie www
du domaine, alors que la page originale que vous avez ouverte est vue sans www
.
typiquement fait pour les Urls canoniques..
j'ai lutté pendant des heures avant de tomber sur cet article et j'ai trouvé l'allusion de Cross Domain.
il me semble que si o.url = 'index.php'
et que ce fichier existe est ok et renvoie un message de succès dans la console. Il retourne une erreur si j'utilise l'url: http://www.google.com
si vous faites une requête post pourquoi ne pas utiliser directement le $.post méthode:
$.post("test.php", { func: "getNameAndTime" },
function(data){
alert(data.name); // John
console.log(data.time); // 2pm
}, "json");
C'est tellement plus simple.
j'ai posté un exemple clair de la façon de résoudre ceci si contrôler le code du serveur du domaine dans lequel vous postez. Cette réponse est abordée dans ce fil, mais cela l'explique plus clairement IMO.
Comment puis-je envoyer une demande postale trans-domaine via JavaScript?
Solution à cette question est:
- utiliser le type de données:
json
- ajouter
&callback=?
à votre url
cela a fonctionné sur l'appel de L'API Facebook et avec Firefox. Firebug utilise GET
au lieu de OPTIONS
avec les conditions ci-dessus (les deux).
une autre possibilité pour contourner le problème est d'utiliser un script proxy. Cette méthode est décrite pour exemple ici
Pouvez-vous l'essayer sans
contentType:application/x-www-form-urlencoded
function test_success(page,name,id,divname,str)
{
var dropdownIndex = document.getElementById(name).selectedIndex;
var dropdownValue = document.getElementById(name)[dropdownIndex].value;
var params='&'+id+'='+dropdownValue+'&'+str;
//makerequest_sp(url, params, divid1);
$.ajax({
url: page,
type: "post",
data: params,
// callback handler that will be called on success
success: function(response, textStatus, jqXHR){
// log a message to the console
document.getElementById(divname).innerHTML = response;
var retname = 'n_district';
var dropdownIndex = document.getElementById(retname).selectedIndex;
var dropdownValue = document.getElementById(retname)[dropdownIndex].value;
if(dropdownValue >0)
{
//alert(dropdownValue);
document.getElementById('inputname').value = dropdownValue;
}
else
{
document.getElementById('inputname').value = "00";
}
return;
url2=page2;
var params2 = parrams2+'&';
makerequest_sp(url2, params2, divid2);
}
});
}
j'ai eu un problème similaire en essayant d'utiliser L'API Facebook.
le seul type de contenu qui n'a pas envoyé la demande pré-éclairée semble être juste text/plain... pas le reste des paramètres mentionnés à mozilla ici
- Pourquoi est-ce le seul navigateur qui fait cela?
- pourquoi Facebook ne sait - il pas et n'accepte-t-il pas la demande avant le vol?
FYI: Le Moz doc susmentionné suggère que les en-têtes X-Lori devraient déclencher une requête pré-allumée ... ça ne l'est pas.
vous devez faire un peu de travail du côté du serveur. Je vois que vous utilisez PHP du côté du serveur, mais la solution pour L'application web .NET est ici: ne peut pas définir le type de contenu à 'application/json' dans jQuery.ajax
faites la même chose dans le script PHP et ça marchera. Simplement: à la première demande le navigateur demande au serveur si est autorisé à envoyer de telles données avec un tel type et la deuxième demande est le bon / autorisé.
essayez d'ajouter ce qui suit:
dataType: "json",
ContentType: "application/json",
data: JSON.stringify({"method":"getStates", "program":"EXPLORE"}),
j'ai utilisé une url proxy pour résoudre un problème similaire lorsque je veux poster des données sur mon apache solr hébergé sur un autre serveur. (Cela peut ne pas être la réponse parfaite, mais elle n'en résout mon problème.)
suivez cette URL: en utilisant le Mode-Rewrite pour , j'ajoute cette ligne à mon httpd.conf:
RewriteRule ^solr/(.*)$ http://ip:8983/solr [P]
par conséquent, je peux simplement poster des données à / solr au lieu de poster des données à http://ip:8983/solr / *. Puis il affichera les données dans la même origine.
j'ai déjà ce code qui gère bien Ma situation cors en php:
header( 'Access-Control-Allow-Origin: '.CMSConfig::ALLOW_DOMAIN );
header( 'Access-Control-Allow-Headers: '.CMSConfig::ALLOW_DOMAIN );
header( 'Access-Control-Allow-Credentials: true' );
et il fonctionnait bien localement et à distance, mais pas pour les uploads à distance.
quelque chose se passe avec apache/php ou mon code, je n'ai pas pris la peine de le rechercher, quand vous demandez des OPTIONS il renvoie mon en-tête avec les règles cors mais avec 302 résultat. Par conséquent, mon navigateur ne reconnaît pas comme une situation acceptable.
ce que j'ai fait, basé sur @Mark McDonald réponse, est juste mettre ce code après mon en-tête:
if( $_SERVER['REQUEST_METHOD'] === 'OPTIONS' )
{
header("HTTP/1.1 202 Accepted");
exit;
}
Maintenant, lorsque vous demandez OPTIONS
il vous suffit d'envoyer l'en-tête et 202 résultat.
s'il vous Plaît noter:
JSONP supporte uniquement la méthode GET request.
*Envoyer la demande par la firefox :*
$.ajax({
type: 'POST',//<<===
contentType: 'application/json',
url: url,
dataType: "json"//<<=============
...
});
ci-dessus Demande envoyée par OPTIONS (while ==> type: 'POST' )!!!!
$.ajax({
type: 'POST',//<<===
contentType: 'application/json',
url: url,
dataType: "jsonp"//<<==============
...
});
mais au-dessus de la demande envoyer par GET (while = = > type: 'POST' )!!!!
lorsque vous êtes en "communication inter-domaines", faites attention et soyez prudent.