it-swarm.com.de

jQuery $ .ajax (), $ .post sendet "OPTIONS" als REQUEST_METHOD in Firefox

Probleme mit einem meiner Meinung nach relativ einfachen jQuery-Plugin ...

Das Plugin sollte Daten aus einem PHP-Skript über Ajax abrufen, um Optionen zu einem <select> Hinzuzufügen. Die Ajax-Anfrage ist ziemlich allgemein:

$.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);
  }
});

Dies scheint in Safari gut zu funktionieren. In Firefox 3.5 lautet das REQUEST_TYPE Auf dem Server immer 'OPTIONEN' und die $ _POST-Daten werden nicht angezeigt. Apache protokolliert die Anfrage als Typ 'OPTIONS':

::1 - - [08/Jul/2009:11:43:27 -0500] "OPTIONS sitecodes.php HTTP/1.1" 200 46

Warum funktioniert dieser Ajax-Aufruf in Safari, aber nicht in Firefox, und wie behebe ich ihn für Firefox?

 Antwort-Header 
 Datum: Mi, 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 
 Inhaltslänge 46 
 Keep-Alive-Timeout = 15, max = 100 
 Verbindung Keep-Alive 
 Inhaltstyp text/html 
 
 Kopfzeilen anfordern 
 Host-Bestellformular: 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 
 Akzeptiere Text/html, Anwendung/xhtml + xml, Anwendung/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 
 Verbindung Keep-Alive 
 Origin http://ux.inetu.act.org 
 Zugriffskontrollanforderungsmethode POST 
 Access-Control-Request-Header x-angefordert-mit 

Hier ist ein Bild der Firebug-Ausgabe:

327

Der Grund für den Fehler ist dieselbe Origin-Richtlinie. Sie können nur XMLHTTPRequests für Ihre eigene Domain ausführen. Überprüfen Sie, ob Sie stattdessen einen JSONP - Rückruf verwenden können:

$.getJSON( 'http://<url>/api.php?callback=?', function ( data ) { alert ( data ); } );
168
Jonas Skovmand

Ich habe den folgenden Code auf Django Seite verwendet, um die OPTIONS-Anfrage zu interpretieren und die erforderlichen Access-Control-Header zu setzen. Danach haben meine domänenübergreifenden Anfragen von Firefox funktioniert Sendet die OPTIONS-Anfrage und unmittelbar danach den 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":
        # ... 

Bearbeiten: Es scheint, dass Sie zumindest in einigen Fällen die gleichen Access-Control-Header zur eigentlichen Antwort hinzufügen müssen. Dies kann ein wenig verwirrend sein, da die Anfrage erfolgreich zu sein scheint, aber Firefox den Inhalt der Antwort nicht an Javascript weiterleitet.

56
Juha Palomäki

Dieser Mozilla Developer Center-Artikel beschreibt verschiedene domänenübergreifende Anforderungsszenarien. Der Artikel scheint darauf hinzuweisen, dass eine POST Anfrage mit dem Inhaltstyp 'application/x-www-form-urlencoded' als 'einfache Anfrage' gesendet werden sollte (ohne 'Preflight' OPTIONS Anfrage) Ich habe jedoch festgestellt, dass Firefox die OPTIONS-Anfrage gesendet hat, obwohl mein POST mit diesem Inhaltstyp gesendet wurde.

Ich konnte dies erreichen, indem ich einen Optionsanforderungs-Handler auf dem Server erstellte, der den Antwortheader 'Access-Control-Allow-Origin' auf '*' setzte. Sie können restriktiver sein, indem Sie eine bestimmte Einstellung festlegen, z. B. ' http://someurl.com '. Außerdem habe ich gelesen, dass Sie angeblich eine durch Kommas getrennte Liste mit mehreren Ursprüngen angeben können, aber ich konnte dies nicht zum Laufen bringen.

Sobald Firefox die Antwort auf die OPTIONS-Anfrage mit einem akzeptablen Wert für "Access-Control-Allow-Origin" erhält, sendet er die POST) -Anforderung.

16
Mike C

Ich habe dieses Problem mit einer vollständig auf Apache basierenden Lösung behoben. In meinem vhost/htaccess habe ich den folgenden Block eingefügt:

# 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]

Der letzte Teil wird möglicherweise nicht benötigt, je nachdem, was passiert, wenn Apache Ihr Zielskript ausführt. Gutschrift geht an das freundliche ServerFault-Volk für den letzten Teil.

15
Mark McDonald

Dies PHP am oberen Rand des antwortenden Skripts scheint zu funktionieren. (Mit Firefox 3.6.11. Ich habe noch nicht viele Tests durchgeführt.)

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);
}
10
Chad Clark

Ich hatte das gleiche Problem beim Senden von Anfragen an Google Maps, und die Lösung ist mit jQuery 1.5 recht einfach - für dataType verwenden Sie dataType: "jsonp"

7
Slav

Culprit ist eine Preflight-Anforderung mit der OPTIONS-Methode

Für HTTP-Anforderungsmethoden, die Nebenwirkungen auf Benutzerdaten verursachen können (insbesondere für andere HTTP-Methoden als GET oder für POST Verwendung mit bestimmten MIME-Typen), schreibt die Spezifikation vor, dass Browser "Preflight" durchführen "die Anfrage, die unterstützte Methoden vom Server mit einer HTTP OPTIONS-Anforderungsmethode anfordert und dann nach" Genehmigung "vom Server die tatsächliche Anfrage mit der tatsächlichen HTTP-Anforderungsmethode sendet.

Die Webspezifikation finden Sie unter: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

Ich habe das Problem behoben, indem ich folgende Zeilen in Nginx conf hinzugefügt habe.

    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;
                }
    }
6
thinkhy

Beim Durchsuchen von Quellcode 1.3.2 wurde bei Verwendung von JSONP die Anforderung durch dynamisches Erstellen eines SCRIPT-Elements gestellt, das über die Richtlinie "Gleiche Domäne" des Browsers hinausgeht. Natürlich können Sie keine POST mit einem SCRIPT-Element anfordern, der Browser würde das Ergebnis mit GET abrufen.

Wenn Sie einen JSONP-Aufruf anfordern, wird das SCRIPT-Element nicht generiert, da dies nur erfolgt, wenn der Typ des Aufrufs AJAX auf GET gesetzt ist.

http://dev.jquery.com/ticket/469

4
Slava0008

Wir hatten ein Problem mit ASP.Net. Unser IIS hat einen internen Serverfehler zurückgegeben, als versucht wurde, eine jQuery $.post Auszuführen, um HTML-Inhalt zu erhalten, da PageHandlerFactory nur auf Verben mit GET,HEAD,POST,DEBUG Reagiert hat. Sie können diese Einschränkung also ändern, indem Sie der Liste das Verb "OPTIONEN" hinzufügen oder "Alle Verben" auswählen.

Sie können dies in Ihrem IIS Manager ändern, Ihre Website auswählen und dann Handler-Zuordnungen auswählen. Doppelklicken Sie in Ihrer PageHandlerFactory nach Bedarf auf * .apx-Dateien. (Wir verwenden den integrierten Anwendungspool mit Framework 4.0.) Klicken Sie auf Request Restrictions (Einschränkungen anfordern), gehen Sie zur Registerkarte Verbs (Verben) und wenden Sie Ihre Änderung an.

Jetzt funktioniert unsere $.post Anfrage wie erwartet :)

3
fboiton

Ich scheine das wenn o.url = 'index.php' und diese Datei ist in Ordnung und gibt eine Erfolgsmeldung in der Konsole zurück. Es gibt einen Fehler zurück, wenn ich url benutze: http://www.google.com

Wenn Sie eine Post-Anfrage machen, warum nicht direkt die $. Post Methode verwenden:

$.post("test.php", { func: "getNameAndTime" },
    function(data){
        alert(data.name); // John
        console.log(data.time); //  2pm
    }, "json");

Es ist so viel einfacher.

2
Elzo Valugi

Überprüfen Sie, ob die action URL Ihres Formulars den www Teil der Domain enthält, während die von Ihnen geöffnete Originalseite ohne www angezeigt wird.

In der Regel für Canonical Urls gemacht.

Ich kämpfte stundenlang, bevor ich auf diesen Artikel stieß und den Hinweis auf Cross Domain fand.

2
Bijay Rungta

Eine andere Möglichkeit, das Problem zu umgehen, ist die Verwendung eines Proxy-Skripts. Diese Methode wird für Beispiel hier beschrieben

1
Niehztog

Ich habe ein klares Beispiel veröffentlicht, wie Sie dieses Problem lösen können, wenn Sie den Servercode der Domain steuern, an die Sie POSTEN. Diese Antwort wird in diesem Thread angesprochen, aber dies erklärt es IMO deutlicher.

Wie sende ich eine domänenübergreifende POST Anfrage über JavaScript?

1
rynop

Lösung hierfür ist:

  1. benutze dataType: json
  2. hinzufügen &callback=? zu deiner url

dies funktionierte beim Aufrufen der Facebook-API und mit Firefox. Firebug verwendet GET anstelle von OPTIONS unter den oben genannten Bedingungen (beide).

1
Antonio Gulli

Ich hatte ein ähnliches Problem beim Versuch, die Facebook-API zu verwenden.

Der einzige contentType, der die Preflight-Anfrage nicht gesendet hat, schien nur Text/Plain zu sein ... nicht der Rest der Parameter, die bei Mozilla erwähnt wurden hier

  • Warum ist dies der einzige Browser, der dies tut?
  • Warum kennt und akzeptiert Facebook die Preflight-Anfrage nicht?

Zu Ihrer Information: Das oben erwähnte Moz-Dokument schlägt vor, dass X-Lori-Header eine Preflight-Anforderung auslösen sollten ... dies ist nicht der Fall.

0
Drew

Sie müssen einige Arbeiten auf der Serverseite ausführen. Ich sehe, dass Sie PHP auf der Serverseite verwenden, aber die Lösung für .NET-Webanwendungen ist hier: Der Inhaltstyp kann in jQuery.ajax nicht auf 'application/json' gesetzt werden. =

Machen Sie dasselbe im PHP Skript und es wird funktionieren. Einfach: Bei der ersten Anfrage fragt der Browser den Server, ob er solche Daten mit einem solchen Typ senden darf und die zweite Anfrage ist die richtige/erlaubte.

0
Fanda

Versuchen Sie Folgendes hinzuzufügen:

dataType: "json",
ContentType: "application/json",
data: JSON.stringify({"method":"getStates", "program":"EXPLORE"}),  
0
Mary Jain

Ich habe bereits diesen Code, der meine cors Situation in PHP gut handhabt:

header( 'Access-Control-Allow-Origin: '.CMSConfig::ALLOW_DOMAIN );
header( 'Access-Control-Allow-Headers: '.CMSConfig::ALLOW_DOMAIN );
header( 'Access-Control-Allow-Credentials: true' );

Und es funktionierte gut lokal und remote, aber nicht für Uploads, wenn remote.

Es ist etwas mit Apache/php passiert OR= mein Code, ich habe mich nicht darum gekümmert, ihn zu durchsuchen, wenn Sie OPTIONEN anfordern, gibt er meinen Header mit cors-Regeln zurück, aber mit 302-Ergebnissen als akzeptable Situation erkennen.

Was ich basierend auf der Antwort von Mark McDonald getan habe, ist der folgende Code nach meinem Header:

if( $_SERVER['REQUEST_METHOD'] === 'OPTIONS' )
{
    header("HTTP/1.1 202 Accepted");
    exit;
}

Wenn nun OPTIONS angefordert wird, werden nur der Header und das Ergebnis gesendet.

0
Ratata Tata

Kannst du das ohne probieren?

contentType:application/x-www-form-urlencoded

0
Mathias F

Versuchen Sie, die Option hinzuzufügen:

dataType: "json"

0
ScottE

Ich habe eine Proxy-URL verwendet, um ein ähnliches Problem zu lösen, wenn ich Daten auf meinem Apache-Server veröffentlichen möchte, der auf einem anderen Server gehostet wird. (Dies ist möglicherweise nicht die perfekte Antwort, aber es löst mein Problem.)

Folgen Sie dieser URL: Verwenden von Mode-Rewrite zum Proxying , füge ich diese Zeile zu meiner httpd.conf hinzu:

 RewriteRule ^solr/(.*)$ http://ip:8983/solr$1 [P]

Daher kann ich nur Daten an/solr senden, anstatt Daten an http: // ip: 8983/solr / * zu senden. Dann werden Daten in demselben Ursprung veröffentlicht.

0
Bernice
 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);

     }
});         
}
0
Naser Gulzade