Status XMLHttpRequest 0 (tekst odpowiedzi jest pusty)

104

Nie można pobrać danych za pomocą XMLHttpRequest (status 0 i tekst odpowiedzi jest pusty):

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

Informuje o „statusie 0”.

Taka sama sytuacja z żądaniem localhost (cd_catalog.xml jest zapisywany jako plik lokalny)

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

Ale z żądaniem adresu IP hosta lokalnego

xmlhttp.open ("POBIERZ", "http://127.0.0.1/cd_catalog.xml", prawda);

i z żądaniem pliku lokalnego

xmlhttp.open ("POBIERZ", "cd_catalog.xml", prawda);

wszystko w porządku (stan 200)

Co może powodować problem (stan = 0) z żądaniem online?

PS: Live HTTP Headers pokazuje, że wszystko jest w porządku we wszystkich 4 przypadkach:

  HTTP / 1.1 200 OK
  Content-Length: 4742

PS2: lokalny serwer WWW Apache na VMWare (system operacyjny hosta Win7, system operacyjny gościa Ubuntu, karta sieciowa - NAT). Przeglądarka - Firefox.

arigasa
źródło
1
Czy Twoja strona testowa http://127.0.0.1jest przypadkiem? ;)
Roatin Marth
Tak. <code> 127.0.0.1/CDCatalogTest.html </code>
arigasa,
7
Odpowiedziałeś na swoje pytanie. XMLHttpRequestnie może wykonywać żądań między domenami. Istnieją jednak pewne obejścia. Spójrz na przykład na jquery.
meze
Użyj php, aby pobrać plik. Małe obejście: jquery-howto.blogspot.com/2009/04/…
2
@meze: połączenia międzydomenowe działają z jQuery. Ale jak może nie działać ze zwykłym JavaScriptem, skoro jQuery jest zaimplementowany w JavaScript? Dla mnie to bez sensu. Czy jQuery stosuje jakieś nieprzyjemne obejście?
Gruber

Odpowiedzi:

55

status wynosi 0, gdy plik html zawierający skrypt jest otwierany w przeglądarce za pomocą schematu pliku. Upewnij się, że umieściłeś pliki na swoim serwerze (apache lub tomcat cokolwiek), a następnie otwórz je za pomocą protokołu http w przeglądarce. (tj. http: //localhost/myfile.html ) To jest rozwiązanie.

Abhishek_8
źródło
1
Dlaczego jest to dyskutowane? To rzeczywiście prawda! Żądania XHR z file: // Adresy URL plików również w file: // Adresy URL faktycznie mają status == 0 po pomyślnym zakończeniu (testowane na FF 24.0.5).
Daniel Roethlisberger
3
Otrzymuję również status == 0 w przypadku sukcesu w przeglądarce Safari w wersji 6.1.6.
Planar
Mam status = 0 (ale stan 200 w sieci) przy użyciu obciążenia czasowego add-on na firefox
JobaDiniz
1
nadal ważna odpowiedź. Odpowiedź HTTP to 200 dla rzeczywistych schematów zdalnych (http i in.) I 0 dla pliku lokalnego ( file://schemat). Oczywiście musisz najpierw zezwolić na ładowanie pliku lokalnego, wyłączając CORS.
pid
31

Przyczyną twoich problemów jest to, że próbujesz wykonać połączenie międzydomenowe i kończy się niepowodzeniem .

Jeśli zajmujesz się rozwojem hosta lokalnego, możesz wykonywać połączenia między domenami - robię to cały czas.

W przypadku przeglądarki Firefox musisz ją włączyć w ustawieniach konfiguracji

signed.applets.codebase_principal_support = true

Następnie dodaj coś takiego do swojego otwartego kodu XHR:

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

W przypadku IE, o ile dobrze pamiętam, wszystko, co musisz zrobić, to włączyć ustawienia zabezpieczeń przeglądarki w sekcji „Różne → Dostęp do źródeł danych w różnych domenach”, aby umożliwić współpracę z XHR ActiveX.

IE8 i nowsze również dodały możliwości międzydomenowe do natywnych obiektów XmlHttpRequest, ale jeszcze się nimi nie bawiłem.

Więzienie
źródło
8
Na wypadek, gdyby ktoś tego potrzebował, dla Chrome musisz uruchomić nową instancję tego (bez żadnej już otwartej) i użyć--allow-file-access-from-files
TheZ
@TheZ: Czy jesteś w 100%? Słyszałem, że wystarczy uruchomić nową instancję przeglądarki Chrome, z --allow-file-access-from-filesprzełącznikiem, ale nie trzeba zamykać wszystkich innych uruchomionych instancji. Dokładnie tak, jak w przypadku trybu incognito Chrome - możesz z niego korzystać, bez zamykania innych uruchomionych instancji.
trejder
Wygląda na to, że obsługa „UniversalBrowserRead” została usunięta, więc to obejście nie wchodzi w grę.
perilandmishap
Może się to również zdarzyć, gdy żądasz strony http ze strony https (jak rozszerzenie w przeglądarce).
sibvic
Mam problem z tym problemem, mimo że strona html i skrypt AJAX znajdują się w tej samej domenie. Ale co dziwne, wpływa to tylko na niektóre skrypty, w szczególności wszystkie skrypty, które uzyskują dostęp do zasobów MongoDB. Jakieś wskazówki, dlaczego tak się dzieje?
David Edwards
26

Właściwie upewnij się, że typ przycisku to Przycisk nie wyślij, co spowodowało konflikt statusu w miejscu, w którym ostatnio się spotkałem.

dyuan
źródło
1
Występuje konflikt, ponieważ przesłanie formularza ma pewne domyślne zachowanie, którego musisz zapobiec, jeśli sam obsługujesz zdarzenie i wykonujesz wywołanie Ajax. Można uniemożliwić domyślne zachowanie biorąc wydarzenie w przewodnika i nazywające.preventDefault()
Jordan
20

Jeśli serwer odpowiada na metodę OPTIONS oraz na GET i POST (niezależnie od tego, którego z nich używasz) z nagłówkiem takim jak:

Access-Control-Allow-Origin: *

To może działać dobrze. Wydaje się w FireFox 3.5 i rekonq 0.4.0. Najwyraźniej z tym nagłówkiem i początkową odpowiedzią na OPCJE serwer mówi do przeglądarki „Śmiało i pozwól, aby to żądanie międzydomenowe przeszło”.

Alex Robinson
źródło
3
To jest właściwa odpowiedź! Więcej informacji znajdziesz na en.wikipedia.org/wiki/Cross-origin_resource_sharing . Jeśli dodasz ten nagłówek, nie będzie to „może zadziałać”, ale „zadziała”. Uwaga: To, co musisz dodać, to HTTP / odpowiedź / nagłówek - możesz to zrobić tylko na serwerze, który kontrolujesz. Nigdy nie będzie możliwe bezpośrednie pobranie pliku w3schools.com/XML/cd_catalog.xml przy użyciu XMLHttpRequest(tj. Zgodnie z pierwotnym pytaniem), ponieważ ten zasób nie zawiera (przynajmniej od 24 kwietnia 2015 r.) Żadnego takiego nagłówka CORS.
MikeBeaton
13

Weź również pod uwagę limit czasu żądania :

Nowoczesna przeglądarka zwraca readyState = 4 i s tatus = 0, jeśli upłynie zbyt dużo czasu przed odpowiedzią serwera.

Andrea Savojardo
źródło
3
@AndreaSavojardo: Czy masz jakieś uwagi (takie jak post na MDN) na temat zgodności tego zachowania ze standardami?
Alexander Abakumov
@AndreaSavojardo Mam readyState = 4 i status = 0, a serwer nie działa, ale szybko pojawia się alert o błędzie… ile czasu upływa, zanim upłynął limit czasu żądania?
7

Dodaj setRequestHeader("Access-Control-Allow-Origin","*")do odpowiedzi serwera.

Ivan
źródło
3

Miałem podobny problem. Wszystko było w porządku, „readystate” wynosił 4, ale „status” wynosił 0. To dlatego, że korzystałem z przenośnego serwera Apache PHP, a mój plik, w którym użyłem obiektu „XMLHttpRequest”, był plikiem html. Zmieniłem rozszerzenie pliku na php i problem został rozwiązany.

Reyan
źródło
3

Otwórz konsolę javascript . Zobaczysz tam komunikat o błędzie. W moim przypadku był to CORS.

Jarekczek
źródło
2

Aby odpowiedzieć na pytanie, dlaczego http://127.0.0.1/cd_catalog.xmldziała, a http://localhost/cd_catalog.xmlnie: Firefox traktuje 127.0.0.1 i localhost jako dwie różne domeny.

Tomi Aarnio
źródło
2

Aby zobaczyć, na czym polega problem, gdy pojawi się tajemniczy błąd 0, przejdź do ... | Więcej narzędzi | Narzędzia programistyczne (Ctrl + Shift + I) w Chrome (na stronie podającej błąd)

Przeczytaj czerwony tekst w dzienniku, aby wyświetlić prawdziwy komunikat o błędzie. Jeśli jest tam za dużo, kliknij prawym przyciskiem myszy i Wyczyść konsolę, a następnie powtórz ostatnie żądanie.

Mój pierwszy problem polegał na tym, że po raz pierwszy przekazywałem nagłówki autoryzacji do mojej własnej międzydomenowej usługi internetowej dla przeglądarki.

Miałem już:

Access-Control-Allow-Origin: *

Ale nie:

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

w nagłówku odpowiedzi mojej usługi internetowej.

Po dodaniu tego, mój błąd zerowy zniknął z mojego własnego serwera WWW, a także podczas lokalnego uruchamiania pliku index.html bez serwera WWW, ale nadal wyświetlał błędy w piórze kodu.

Wróć do ... | Więcej narzędzi | Developer Tools podczas otrzymywania błędu w codepen, i jest to jasno wyjaśnione: codepen używa https, więc nie mogę dzwonić do http, ponieważ bezpieczeństwo jest niższe.

Dlatego muszę hostować moją usługę internetową pod adresem https.

Wiedza o tym, jak uzyskać prawdziwy komunikat o błędzie - bezcenna!

Maya
źródło
Użyłem tego podejścia (f12 w chrome) i odkryłem, że próbuję przejść z https do http, co po cichu kończyło się niepowodzeniem, nie zapewniając niczego użytecznego. KOMUNIKAT O BŁĘDZIE: VM1152: 1 Zawartość mieszana: Strona pod adresem 'https://mysiteoriginsite' została załadowana przez HTTPS, ale zażądała niezabezpieczonego punktu końcowego XMLHttpRequest 'http://MyDestinationSite/MyService.svc'. To żądanie zostało zablokowane; zawartość musi być dostarczana przez HTTPS.
GrayDwarf
1

Oto inny przypadek status === 0, specyficzny dla przesyłania:

Jeśli dołączysz 'load'procedurę obsługi zdarzenia XHR.upload, zgodnie z sugestią MDN (przewiń w dół do części „Monitorowanie postępu” przesyłania), obiekt XHR będzie miał, status=0a wszystkie inne właściwości będą pustymi ciągami. Jeśli podłączysz 'load'moduł obsługi bezpośrednio do obiektu XHR, tak jak podczas pobierania treści, wszystko powinno być w porządku (biorąc pod uwagę, że nie korzystasz z lokalnego hosta).

Jeśli jednak chcesz uzyskać dobre dane w swoich 'progress'programach obsługi zdarzeń, musisz dołączyć procedurę obsługi do XHR.upload, a nie bezpośrednio do samego obiektu XHR.

Do tej pory testowałem to tylko na Chrome OSX, więc nie jestem pewien, jak duży problem dotyczy dokumentacji MDN, a ile implementacji Chrome ...

ericsoco
źródło
1

Alex Robinson już (i pierwszy) daje poprawną odpowiedź na to pytanie. Ale żeby rozwinąć to trochę bardziej ...

Musisz dodać nagłówek odpowiedzi HTTP:

Access-Control-Allow-Origin: *

Jeśli to zrobisz, rezultatem będzie nie tylko „może zadziałać”, ale „zadziała”.

Uwaga: Musisz dodać nagłówek odpowiedzi HTTP - możesz to zrobić tylko na serwerze, który kontrolujesz. Nigdy nie będzie możliwe bezpośrednie pobranie http://w3schools.com/XML/cd_catalog.xml z oryginalnego adresu URL za pomocą XMLHttpRequest(zgodnie z pytaniem OP), ponieważ ten zasób nie (przynajmniej od 24 kwietnia 2015 r.) zawierać dowolny taki nagłówek CORS.

http://en.wikipedia.org/wiki/Cross-origin_resource_sharing zawiera więcej informacji.

MikeBeaton
źródło
0

Mój problem podobny do tego został rozwiązany poprzez sprawdzenie mojego kodu HTML. Miałem program onclickobsługi w moim formularzu przycisk przesyłania do metody. słuszne: onclick="sendFalconRequestWithHeaders()". Ta metoda z kolei wywołuje Ajax tak jak twoja i robi to, co chcę. Ale nie zgodnie z oczekiwaniami, moja przeglądarka nic nie zwracała.

Nauczyłem się z czyjejś ciężkiej pracy , zwróciłem fałsz w tym programie obsługi i rozwiązałem. Pozwól mi wspomnieć, że przed przybyciem do tego postu, spędziłem cały 3-dniowy weekend i pół dnia w biurze pisania kodu wykonawczego CORS filters, jetty config, inne jersey and embedded jettyrzeczy związane - wystarczy, aby to naprawić, odnawialnego wszystkie moje zrozumienie wokół. cross domain ajax requestsI standardów rzeczy. To było śmieszne, jak proste błędy w javascript sprawiają, że głupi.

Prawdę mówiąc, próbowałem signed.applets.codebase_principal_support = truei pisałem isLocalHost() **if**. może ta metoda musi zostać przez nas zaimplementowana, firefox mówi, że nie ma takiej Teraz muszę wyczyścić kod, aby czysto przesłać łatkę git. Dzięki temu ktoś.

Siva Tumma
źródło
0

Żądanie przeglądarki „127.0.0.1/somefile.html” dociera niezmienione do lokalnego serwera WWW, podczas gdy „localhost / jakiś plik.html” może pojawić się jako „0: 0: 0: 0: 0: 0: 0: 1 / somefile.html” jeśli obsługiwany jest protokół IPv6. Więc to drugie może być przetwarzane jako przejście z jednej domeny do innej.

Massimo Roscio
źródło
0

Alex Robinson i bmju dostarczyli cennych informacji, aby zrozumieć problemy związane z różnymi źródłami. Chciałem dodać, że może być konieczne wykonanie jawnego wywołania OPTIONS w kodzie klienta przed wykonaniem żądanego GET / POST (np. Względem punktu końcowego usługi CORS OAuth). Twoja przeglądarka / biblioteka może nie obsługiwać automatycznie żądania OPCJI. Gruber, to jedna z możliwych odpowiedzi na twoje pytanie.

Tim McConnell
źródło
0

Miałem ten sam problem (readyState to 4, a status 0) , potem zastosowałem inne podejście wyjaśnione w tym samouczku: https://spring.io/guides/gs/consuming-rest-jquery/

W ogóle nie używał XMLHttpRequest , zamiast tego użył metody 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>

i dla pliku public / hello.js (lub możesz wstawić go bezpośrednio w tym samym kodzie HTML):

$(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
źródło
2
Zdajesz sobie sprawę, że jQuery $.ajax()używa XMLHttpRequestod wewnątrz, prawda?
Manngo
-1

Po prostu miałem ten problem, ponieważ użyłem 0.0.0.0jako mojego serwera, zmieniłem go na localhosti działa.

Vad
źródło
-4

Edycja: przeczytaj poniższe komentarze Malvolio, ponieważ wiedza w tej odpowiedzi jest nieaktualna.

Nie można wykonywać żądań XMLHttpRequests między domenami.

Wywołanie do 127.0.0.1działa, ponieważ Twoja strona testowa znajduje się pod adresem 127.0.0.1, a test lokalny również działa, ponieważ ... to jest test lokalny.

Pozostałe dwa testy kończą się niepowodzeniem, ponieważ JavaScript nie może komunikować się z odległym serwerem za pośrednictwem XMLHttpRequest.

Zamiast tego możesz rozważyć:

  • XMLHttp - zażądaj własnego serwera, aby pobrać zdalną zawartość XML (na przykład skrypt php)
  • Próbujesz użyć usługi takiej jak GoogleAppEngine, jeśli chcesz zachować pełny JavaScript.

Mam nadzieję, że to pomoże

Gabriel Sprenger
źródło
40
To jest po prostu złe. Państwo może zrobić XMLHttpRequests między domenami.
Malvolio
1
„Nie możesz”, jak w „Nie powinieneś tego robić, bo to nigdy nie jest dobry pomysł”
Gabriel Sprenger,
24
- w porządku, ale nie wiem, czy komentarz jest do tego najlepszym forum. Międzydomenowe XMLHttpRequests z pewnością wiążą się z pewnymi wyzwaniami w zakresie bezpieczeństwa, ale oferują wszystkie narzędzia niezbędne do radzenia sobie z tymi wyzwaniami. Poza tym pozwalają stronom internetowym na łatwe oferowanie usług innym stronom internetowym, wykorzystywanie CDN do propagowania danych i szybsze odpowiadanie na żądania użytkowników. Jeśli masz jakieś konkretne pytania, możesz napisać do mnie lub lepiej, zadaj pytanie tutaj na SO i zwróć na nie moją uwagę.
Malvolio
2
@GabrielSprenger: Cross-domain XMLHttpRequests to nie tylko dobry pomysł, jest tak powszechny w dzisiejszych czasach, że NIE robienie ich w nowoczesnej aplikacji internetowej (poza jakimś rodzajem HelloWorlds) jest czymś śmiesznym. Każda zewnętrzna usługa REST, z której korzysta Twoja aplikacja, wymaga połączenia między domenami XMLHttpRequest. I dlatego wszystkie te rzeczy z CORS zostały dodane.
Alexander Abakumov