XMLHttpRequest Status 0 (responseText ist leer)

104

Mit XMLHttpRequest können keine Daten abgerufen werden (Status 0 und responseText sind leer):

xmlhttp = new XMLHttpRequest ();
xmlhttp.open ("GET", "http://www.w3schools.com/XML/cd_catalog.xml", true);
xmlhttp.onreadystatechange = function () 
{
  if (xmlhttp.readyState == 4)
    alert ("status" + xmlhttp.status);
}}
xmlhttp.send ();

Es warnt "Status 0".

Die gleiche Situation mit der localhost-Anforderung (cd_catalog.xml wird als lokale Datei gespeichert)

xmlhttp.open ("GET", "http: //localhost/cd_catalog.xml", true);

Aber mit der localhost IP Anfrage

xmlhttp.open ("GET", "http://127.0.0.1/cd_catalog.xml", true);

und mit der lokalen Dateianforderung

xmlhttp.open ("GET", "cd_catalog.xml", true);

alles ist in Ordnung (Status 200)

Was kann das Problem (Status = 0) bei der Online-Anfrage verursachen?

PS: Live-HTTP-Header zeigen, dass in allen 4 Fällen alles in Ordnung ist:

  HTTP / 1.1 200 OK
  Inhaltslänge: 4742

PS2: Apache lokaler Webserver unter VMWare (Host-Betriebssystem Win7, Gast-Betriebssystem Ubuntu, Netzwerkadapter - NAT). Browser - Firefox.

Arigasa
quelle
1
Ist Ihre Testseite http://127.0.0.1zufällig? ;)
Roatin Marth
Ja. <code> 127.0.0.1/CDCatalogTest.html </ code>
Arigasa
7
Sie haben Ihre Frage beantwortet. XMLHttpRequestdomänenübergreifende Anfragen können nicht gestellt werden. Es gibt jedoch einige Problemumgehungen. Schauen Sie sich zum Beispiel jquery an.
Meze
Verwenden Sie PHP, um die Datei zu erhalten. Kleine Problemumgehung
2
@meze: Domänenübergreifende Aufrufe funktionieren mit jQuery. Aber wie kann es nicht mit einfachem JavaScript funktionieren, da jQuery in JavaScript implementiert ist? Es ergibt keinen Sinn für mich. Verwendet jQuery eine böse Problemumgehung?
Gruber

Antworten:

55

Der Status ist 0, wenn Ihre HTML-Datei mit dem Skript über das Dateischema im Browser geöffnet wird. Stellen Sie sicher, dass Sie die Dateien auf Ihrem Server ablegen (Apache oder Tomcat) und öffnen Sie sie dann über das http-Protokoll im Browser. (dh http: //localhost/myfile.html ) Dies ist die Lösung.

Abhishek_8
quelle
1
Warum wird dies abgelehnt? Es ist tatsächlich wahr! XHR-Anforderungen von Datei: // URLs von Dateien, die sich ebenfalls in Datei befinden: // URLs haben bei Erfolg tatsächlich den Status == 0 (getestet auf FF 24.0.5).
Daniel Roethlisberger
3
Ich erhalte auch den Status == 0 für den Erfolg von Safari Version 6.1.6.
Planar
Ich habe Status = 0 (aber Status 200 im Netzwerk) mit temporären Add-On auf Firefox
laden
1
noch gültige Antwort. Die HTTP-Antwort beträgt 200 für tatsächliche Remote-Schemata (http et al.) Und 0 für lokale Dateien ( file://Schema). Natürlich müssen Sie zuerst das Laden lokaler Dateien zulassen, indem Sie CORS deaktivieren.
Pid
31

Die Ursache für Ihre Probleme ist, dass Sie versuchen, einen domänenübergreifenden Anruf zu tätigen, der fehlschlägt .

Wenn Sie localhost entwickeln, können Sie domänenübergreifende Anrufe tätigen - ich mache das die ganze Zeit.

Für Firefox müssen Sie es in Ihren Konfigurationseinstellungen aktivieren

signed.applets.codebase_principal_support = true

Fügen Sie dann Ihrem offenen XHR-Code Folgendes hinzu:

  if (isLocalHost()){
    if (typeof(netscape) != 'undefined' && typeof(netscape.security) != 'undefined'){
      netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');
    }
  }

Wenn ich mich recht erinnere, müssen Sie für IE lediglich die Sicherheitseinstellung des Browsers unter "Verschiedenes → Domänenübergreifend auf Datenquellen zugreifen" aktivieren, damit er mit ActiveX XHRs funktioniert.

IE8 und höher haben auch domänenübergreifende Funktionen zu den nativen XmlHttpRequest-Objekten hinzugefügt, aber ich habe noch nicht mit diesen gespielt.

Knast
quelle
8
Falls jemand es benötigt, müssen Sie für Chrome eine neue Instanz davon starten (ohne dass eine bereits geöffnet ist) und--allow-file-access-from-files
TheZ
@ TheZ: Bist du 100%? Ich habe gehört, dass Sie nur eine neue Instanz von Chrome mit --allow-file-access-from-filesSchalter ausführen müssen , aber nicht alle anderen laufenden Instanzen schließen müssen. Genau wie im Chrome Incognito-Modus können Sie ihn verwenden, ohne andere laufende Instanzen zu schließen.
Trejder
Es sieht so aus, als ob die Unterstützung für 'UniversalBrowserRead' eingestellt wurde, daher ist diese Problemumgehung keine Option.
Perilandmishap
Dies kann auch passieren, wenn Sie eine http-Seite von einer https-Seite anfordern (z. B. eine Erweiterung im Browser).
Sibvic
Dieses Problem tritt auf, obwohl sich die HTML-Seite und das AJAX-Skript in derselben Domäne befinden. Aber seltsamerweise betrifft es nur einige Skripte, insbesondere alle Skripte, die auf MongoDB-Ressourcen zugreifen. Irgendwelche Hinweise, warum das so ist?
David Edwards
26

Stellen Sie sicher, dass Ihr Schaltflächentyp "Schaltfläche nicht senden" ist, was zu einem Statuskonflikt geführt hat, den ich kürzlich getroffen habe.

Dyuan
quelle
1
Es liegt ein Konflikt vor, da das Senden eines Formulars ein Standardverhalten aufweist, das Sie verhindern müssen, wenn Sie das Ereignis behandeln und selbst einen Ajax-Anruf tätigen. Sie können das Standardverhalten verhindern, indem Sie das Ereignis in Ihrem Handler übernehmen und anrufene.preventDefault()
Jordanien
20

Wenn der Server auf eine OPTIONS-Methode und auf GET und POST (je nachdem, welche Sie verwenden) mit einem Header wie folgt antwortet:

Access-Control-Allow-Origin: *

Es könnte in Ordnung funktionieren. Scheint in FireFox 3.5 und rekonq 0.4.0. Anscheinend sagt der Server mit diesem Header und der ersten Antwort auf OPTIONEN zum Browser: "Fahren Sie fort und lassen Sie diese domänenübergreifende Anforderung durchlaufen."

Alex Robinson
quelle
3
Das ist die richtige Antwort! Weitere Informationen finden Sie unter en.wikipedia.org/wiki/Cross-origin_resource_sharing . Wenn Sie diesen Header hinzufügen, ist es nicht "könnte funktionieren", sondern "wird funktionieren". Hinweis: Sie müssen ein HTTP / eine Antwort / einen Header hinzufügen. Sie können dies also nur auf einem Server tun, den Sie steuern. Es wird niemals möglich sein, w3schools.com/XML/cd_catalog.xml direkt mit XMLHttpRequest(dh gemäß der ursprünglichen Frage) abzurufen , da diese Ressource (zumindest ab dem 24. April 2015) keinen solchen CORS-Header enthält.
MikeBeaton
13

Berücksichtigen Sie auch das Anforderungszeitlimit :

Moderne Browser geben readyState = 4 und s tatus = 0 zurück, wenn vor der Serverantwort zu viel Zeit vergeht.

Andrea Savojardo
quelle
3
@AndreaSavojardo: Haben Sie einen Hinweis (wie einen Beitrag auf MDN), ob dieses Verhalten den Standards entspricht?
Alexander Abakumov
@AndreaSavojardo Ich habe readyState = 4 und status = 0 und der Server läuft nicht, aber die Fehlerwarnung wird mir schnell angezeigt. Wie viel Zeit vergeht für "Anforderungszeitüberschreitung"?
7

Fügen Sie setRequestHeader("Access-Control-Allow-Origin","*")Ihrer Serverantwort hinzu.

Ivan
quelle
3

Ich hatte ein ähnliches Problem. Alles war in Ordnung, der "Readystate" war 4, aber der "Status" war 0. Dies lag daran, dass ich einen tragbaren Apache PHP-Server verwendete und meine Datei, in der ich das "XMLHttpRequest" -Objekt verwendete, eine HTML-Datei war. Ich habe die Dateierweiterung in PHP geändert und das Problem wurde behoben.

Reyan
quelle
3

Öffnen Sie die Javascript-Konsole . Dort wird eine Fehlermeldung angezeigt. In meinem Fall war es CORS.

Jarekczek
quelle
2

Zur Beantwortung der Frage, warum http://127.0.0.1/cd_catalog.xmlfunktioniert , während http://localhost/cd_catalog.xmlnicht: Firefox behandelt 127.0.0.1 und localhost als zwei verschiedene Domänen.

Tomi Aarnio
quelle
2

Um zu sehen, wo das Problem liegt, gehen Sie zu ... |, wenn Sie den kryptischen Fehler 0 erhalten Weitere Tools | Entwicklertools (Strg + Umschalt + I) in Chrome (auf der Seite mit dem Fehler)

Lesen Sie den roten Text im Protokoll, um die wahre Fehlermeldung zu erhalten. Wenn zu viel drin ist, klicken Sie mit der rechten Maustaste und klicken Sie auf Konsole löschen. Führen Sie dann Ihre letzte Anfrage erneut aus.

Mein erstes Problem war, dass ich zum ersten Mal Autorisierungsheader an meinen eigenen domänenübergreifenden Webdienst für den Browser übergab.

Ich hatte bereits:

Access-Control-Allow-Origin: *

Aber nicht:

Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Authorization

im Antwortheader meines Webdienstes.

Nachdem ich das hinzugefügt hatte, war mein Fehler Null von meinem eigenen Webserver sowie beim lokalen Ausführen der Datei index.html ohne Webserver verschwunden, gab aber immer noch Fehler im Codestift aus.

Zurück zu ... | Weitere Tools | Entwicklertools, während der Fehler in Codepen angezeigt wird, und es wird klar erklärt: Codepen verwendet https, daher kann ich http nicht aufrufen, da die Sicherheit geringer ist.

Ich muss daher meinen Webdienst auf https hosten.

Wissen, wie man die wahre Fehlermeldung erhält - von unschätzbarem Wert!

Maya
quelle
Ich habe diesen Ansatz verwendet (f12 in Chrome) und festgestellt, dass ich versucht habe, von https zu http zu wechseln, was stillschweigend fehlschlug, ohne etwas Nützliches bereitzustellen. FEHLERMELDUNG: VM1152: 1 Gemischter Inhalt: Die Seite bei 'https://mysiteoriginsite' wurde über HTTPS geladen, forderte jedoch einen unsicheren XMLHttpRequest-Endpunkt an 'http://MyDestinationSite/MyService.svc'. Diese Anfrage wurde blockiert. Der Inhalt muss über HTTPS bereitgestellt werden.
GrayDwarf
1

Hier ist ein weiterer Fall, in dem status === 0speziell für das Hochladen:

Wenn Sie einen 'load'Ereignishandler anhängen XHR.upload, wie von MDN vorgeschlagen (scrollen Sie nach unten zum Upload-Teil von 'Überwachungsfortschritt'), hat das XHR-Objekt status=0und alle anderen Eigenschaften sind leere Zeichenfolgen. Wenn Sie die anhängen'load' Handler wie beim Herunterladen von Inhalten direkt an das XHR-Objekt , sollte dies in Ordnung sein (vorausgesetzt, Sie führen localhost nicht aus).

Wenn Sie jedoch gute Daten in Ihren 'progress'Ereignishandlern erhalten möchten , müssen Sie einen Handler anhängen XHR.upload, nicht direkt an das XHR-Objekt selbst.

Ich habe dies bisher nur unter Chrome OSX getestet, daher bin ich mir nicht sicher, wie groß das Problem hier in der MDN-Dokumentation und inwieweit in der Implementierung von Chrome ist.

ericsoco
quelle
1

Alex Robinson gibt bereits (und zuerst) die richtige Antwort auf dieses Problem. Aber um es etwas näher zu erläutern ...

Sie müssen den HTTP-Antwortheader hinzufügen:

Access-Control-Allow-Origin: *

Wenn Sie dies tun, ist das Ergebnis nicht nur "könnte funktionieren", sondern "wird funktionieren".

NB Was Sie hinzufügen müssen , ist ein HTTP - Antwort - Header - so dass Sie nur diese auf einem Server tun , die Sie steuern. Es wird niemals möglich sein, http://w3schools.com/XML/cd_catalog.xml direkt von seiner ursprünglichen URL mit einem abzurufenXMLHttpRequest (gemäß der Frage des OP) , da diese Ressource dies nicht tut (zumindest nicht ab dem 24. April 2015). Fügen Sie einen solchen CORS-Header hinzu.

http://en.wikipedia.org/wiki/Cross-origin_resource_sharing bietet weitere Informationen.

MikeBeaton
quelle
0

Mein ähnliches Problem wurde durch Überprüfen meines HTML-Codes gelöst. Ich hatte einen onclickHandler in meinem Formular, der die Schaltfläche an eine Methode sendet. so : onclick="sendFalconRequestWithHeaders()". Diese Methode ruft Ajax genau wie Ihre auf und macht, was ich will. Aber nicht wie erwartet gab mein Browser nichts zurück.

Aus der harten Arbeit von jemandem gelernt , habe ich in diesem Handler falsch zurückgegeben und gelöst. Lassen Sie mich erwähne , dass zu diesem Beitrag vor der Ankunft, ich ein ganzes 3-Tage - Wochenend und einen halben Tag im Büro Schreiben von Code ausgegeben habe Implementierung CORS filters, jetty configandere jersey and embedded jettyähnliche Sachen - nur dieses Problem zu beheben, revolvierende alle mein Verständnis um.cross domain ajax requests Und Standards Zeug. Es war lächerlich, wie einfach Fehler in Javascript dich dumm machen.

Um wahr zu sein, habe ich versucht signed.applets.codebase_principal_support = trueund geschrieben isLocalHost() **if**. Möglicherweise muss diese Methode von uns implementiert werden. Firefox sagt, dass es keine solche gibt. Jetzt muss ich meinen Code bereinigen, um den Git-Patch sauber einzureichen. Danke an jemanden.

Siva Tumma
quelle
0

Eine Browseranforderung "127.0.0.1/somefile.html" kommt unverändert auf dem lokalen Webserver an, während "localhost / somefile.html" als "0: 0: 0: 0: 0: 0: 0: 1 / somefile.html" ankommt "wenn IPv6 unterstützt wird. Letztere können also so verarbeitet werden, dass sie von einer Domain zu einer anderen wechseln.

Massimo Roscio
quelle
0

Alex Robinson und bmju lieferten wertvolle Informationen zum Verständnis von Problemen zwischen den Ursprüngen. Ich wollte hinzufügen, dass Sie möglicherweise einen expliziten OPTIONS-Aufruf in Ihrem Client-Code ausführen müssen, bevor Sie den gewünschten GET / POST ausführen (z. B. gegen einen CORS OAuth-Service-Endpunkt). Ihr Browser / Ihre Bibliothek verarbeitet die OPTIONS-Anforderung möglicherweise nicht automatisch. Gruber, dies ist eine der möglichen Antworten auf Ihre Frage.

Tim McConnell
quelle
0

Ich hatte das gleiche Problem (readyState war 4 und Status 0) , dann folgte ich einem anderen Ansatz, der in diesem Tutorial erläutert wurde: https://spring.io/guides/gs/consuming-rest-jquery/

Er hat XMLHttpRequest überhaupt nicht verwendet , sondern die Methode jquery $ .ajax () :

<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script src="hello.js"></script>
</head>

<body>
    <div>
        <p class="greeting-id">The ID is </p>
        <p class="greeting-content">The content is </p>
    </div>
</body>

und für die Datei public / hello.js (oder Sie können sie direkt in denselben HTML-Code einfügen):

$(document).ready(function() 
 {
    $.ajax({
        url: "http://rest-service.guides.spring.io/greeting"
   }).then(function(data) {
      $('.greeting-id').append(data.id);
      $('.greeting-content').append(data.content);
   });
 });
RMDev
quelle
2
Sie erkennen , dass jQuery $.ajax()Anwendungen XMLHttpRequestauf der Innenseite, nicht wahr?
Manngo
-1

Ich hatte gerade dieses Problem, weil ich es 0.0.0.0als Server verwendet habe, es geändert habe localhostund es funktioniert.

Vad
quelle
-4

Bearbeiten: Bitte lesen Sie die Kommentare von Malvolio unten, da das Wissen dieser Antwort veraltet ist.

Sie können keine domänenübergreifenden XMLHttpRequests durchführen.

Der Aufruf von 127.0.0.1funktioniert, weil sich Ihre Testseite unter befindet 127.0.0.1, und der lokale Test funktioniert auch, da ... es sich um einen lokalen Test handelt.

Die beiden anderen Tests schlagen fehl, da JavaScript über XMLHttpRequest nicht mit einem entfernten Server kommunizieren kann.

Sie könnten stattdessen entweder Folgendes in Betracht ziehen:

  • XMLHttp-fordern Sie Ihren eigenen Server auf, Ihren Remote-XML-Inhalt für Sie abzurufen (z. B. PHP-Skript).
  • Versuchen Sie, einen Dienst wie GoogleAppEngine zu verwenden, wenn Sie das vollständige JavaScript beibehalten möchten.

hoffentlich hilft das

Gabriel Sprenger
quelle
40
Das ist einfach falsch. Sie können domänenübergreifende XMLHttpRequests durchführen.
Malvolio
1
"Sie können nicht" wie in "Sie sollten es nicht tun, weil es nie eine gute Idee ist"
Gabriel Sprenger
24
- fair genug, aber ich weiß nicht, ob ein Kommentar das beste Forum dafür ist. Domänenübergreifende XMLHttpRequests haben sicherlich einige Sicherheitsherausforderungen, bieten jedoch alle Tools, die zur Bewältigung dieser Herausforderungen erforderlich sind. Abgesehen davon ermöglichen sie es Websites, anderen Websites problemlos Dienste anzubieten, CDNs zur Datenverbreitung zu verwenden und schneller auf Benutzeranfragen zu reagieren. Wenn Sie spezielle Fragen haben, können Sie mir eine Nachricht senden oder besser eine Frage hier auf SO posten und meine Aufmerksamkeit darauf lenken.
Malvolio
2
@GabrielSprenger: Domainübergreifend XMLHttpRequestist nicht nur eine gute Idee, es ist heutzutage so üblich, dass es lächerlich ist, sie NICHT in einer modernen Web-App (jenseits einer Art von HelloWorlds) zu machen. Für jeden externen REST-Service, den Ihre App verwendet, ist eine domänenübergreifende Verwendung erforderlich XMLHttpRequest. Und deshalb wurde all das CORS-Zeug hinzugefügt.
Alexander Abakumov