XMLHttpRequest status 0 (responseText kosong)

104

Tidak bisa mendapatkan data dengan XMLHttpRequest (status 0 dan responseText kosong):

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

Ini mengingatkan "status 0".

Situasi yang sama dengan permintaan localhost (cd_catalog.xml disimpan sebagai file lokal)

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

Tetapi dengan permintaan IP localhost

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

dan dengan permintaan file lokal

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

semuanya baik-baik saja (status 200)

Apa yang dapat menyebabkan masalah (status = 0) dengan permintaan online?

PS: Header HTTP Langsung menunjukkan bahwa semuanya baik-baik saja dalam 4 kasus:

  HTTP / 1.1 200 Oke
  Panjang Konten: 4742

PS2: Server web lokal Apache di VMWare (host OS Win7, OS Tamu Ubuntu, Adaptor jaringan - NAT). Browser - Firefox.

arigasa
sumber
1
Apakah halaman pengujian Anda http://127.0.0.1kebetulan? ;)
Roatin Marth
Iya. <code> 127.0.0.1/CDCatalogTest.html </code>
arigasa
7
Anda menjawab pertanyaan Anda. XMLHttpRequesttidak dapat melakukan permintaan lintas domain. Ada beberapa solusi. Lihat jquery, misalnya.
meze
Gunakan php untuk mendapatkan file tersebut. Sedikit solusi
2
@meze: Panggilan lintas domain berfungsi dengan jQuery. Tapi bagaimana itu tidak bisa bekerja dengan JavaScript biasa, karena jQuery diimplementasikan dalam JavaScript? Tidak masuk akal bagiku. Apakah jQuery menggunakan semacam solusi buruk?
Gruber

Jawaban:

55

statusnya adalah 0 ketika file html Anda yang berisi skrip dibuka di browser melalui skema file. Pastikan untuk menempatkan file di server Anda (apache atau tomcat apa saja) dan kemudian buka melalui protokol http di browser. (yaitu http: //localhost/myfile.html ) Ini solusinya.

Abhishek_8
sumber
1
Mengapa ini mendapat suara negatif? Itu memang benar! Permintaan XHR dari file: // URL file juga ada di file: // URL sebenarnya memiliki status == 0 pada keberhasilan (diuji pada FF 24.0.5).
Daniel Roethlisberger
3
Saya juga mendapatkan status == 0 untuk kesuksesan di Safari Versi 6.1.6.
Planar
Saya memiliki status = 0 (tetapi status 200 di jaringan) menggunakan Muat add-on sementara di firefox
JobaDiniz
1
jawaban masih valid. Respons HTTP adalah 200 untuk skema jarak jauh aktual (http et al.) Dan 0 untuk file lokal ( file://skema). Jelas, Anda harus mengizinkan pemuatan file lokal terlebih dahulu dengan menonaktifkan CORS.
pid
31

Penyebab masalah Anda adalah Anda mencoba melakukan panggilan lintas domain dan gagal .

Jika Anda melakukan pengembangan localhost, Anda dapat melakukan panggilan lintas domain - Saya melakukannya setiap saat.

Untuk Firefox, Anda harus mengaktifkannya di pengaturan konfigurasi Anda

signed.applets.codebase_principal_support = true

Kemudian tambahkan sesuatu seperti ini ke kode terbuka XHR Anda:

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

Untuk IE, jika saya tidak salah ingat, yang harus Anda lakukan adalah mengaktifkan pengaturan Keamanan browser di bawah "Miscellaneous → Access data sources lintas domain" agar dapat berfungsi dengan ActiveX XHRs.

IE8 dan yang lebih baru juga menambahkan kemampuan lintas domain ke objek XmlHttpRequest asli, tetapi saya belum bermain dengan itu.

Penjara
sumber
8
Jika ada yang membutuhkannya, untuk Chrome Anda perlu meluncurkan contoh baru (tanpa yang sudah terbuka) dan menggunakan--allow-file-access-from-files
TheZ
@TheZ: Apakah Anda 100%? Saya pernah mendengar bahwa Anda hanya perlu menjalankan instance Chrome baru, dengan --allow-file-access-from-filesswitch, tetapi Anda tidak perlu menutup semua instance lain yang sedang berjalan. Persis seperti dalam Mode Penyamaran Chrome - Anda dapat menggunakannya, tanpa menutup instance lain yang sedang berjalan.
trejder
Sepertinya dukungan untuk 'UniversalBrowserRead' telah dihentikan, jadi penyelesaian ini bukanlah suatu pilihan.
perilandmishap
Juga, itu bisa terjadi ketika Anda meminta halaman http dari halaman https (seperti ekstensi dalam browser).
sibvic
Saya mengalami masalah ini, meskipun laman html dan skrip AJAX berada di domain yang sama. Tapi anehnya, ini hanya memengaruhi beberapa skrip, terutama skrip apa pun yang mengakses sumber daya MongoDB. Ada petunjuk mengapa ini terjadi?
David Edwards
26

Sebenarnya pastikan jenis tombol Anda adalah Button not Submit, yang menyebabkan konflik status di mana saya bertemu baru-baru ini.

dyuan
sumber
1
Ada konflik karena mengirimkan formulir memiliki beberapa perilaku default yang perlu Anda cegah jika Anda menangani acara dan membuat panggilan ajax sendiri. Anda dapat mencegah perilaku default dengan mengambil acara di penangan Anda dan menelepone.preventDefault()
Jordan
20

Jika server merespons metode OPTIONS dan GET dan POST (mana pun yang Anda gunakan) dengan header seperti:

Access-Control-Allow-Origin: *

Mungkin berhasil. Sepertinya di FireFox 3.5 dan rekonq 0.4.0. Rupanya, dengan tajuk itu dan respons awal ke OPTIONS, server mengatakan ke browser, "Lanjutkan dan biarkan permintaan lintas domain ini diproses."

Alex Robinson
sumber
3
Ini adalah jawaban yang benar! Lihat en.wikipedia.org/wiki/Cross-origin_resource_sharing untuk info lebih lanjut. Jika Anda menambahkan tajuk ini, ini bukan 'mungkin berhasil', tetapi 'akan berhasil'. NB Yang perlu Anda tambahkan adalah HTTP / response / header - jadi Anda hanya dapat melakukan ini di server yang Anda kontrol. Tidak mungkin untuk mengambil w3schools.com/XML/cd_catalog.xml secara langsung menggunakan XMLHttpRequest(yaitu sesuai pertanyaan awal), karena sumber daya tersebut tidak (setidaknya, mulai 24 Apr 2015) menyertakan header CORS tersebut.
MikeBeaton
13

Pertimbangkan juga permintaan waktu tunggu :

Browser modern mengembalikan readyState = 4 dan s tatus = 0 jika terlalu banyak waktu berlalu sebelum respons server.

Andrea Savojardo
sumber
3
@AndreaSavojardo: Apakah Anda memiliki referensi (seperti posting di MDN) tentang apakah perilaku ini sesuai dengan standar?
Alexander Abakumov
@AndreaSavojardo Saya memiliki readyState = 4 dan status = 0 dan server tidak berjalan tetapi peringatan kesalahan menunjukkan kepada saya dengan cepat .... berapa lama waktu berlalu untuk "permintaan waktu habis"?
7

Tambahkan setRequestHeader("Access-Control-Allow-Origin","*")ke respons server Anda.

Ivan
sumber
3

Saya pernah menghadapi masalah serupa. Semuanya baik-baik saja, "readystate" adalah 4, tetapi "status" adalah 0. Itu karena saya menggunakan server portabel Apache PHP dan file saya di mana saya menggunakan objek "XMLHttpRequest" adalah file html. Saya mengubah ekstensi file menjadi php dan masalahnya teratasi.

Reyan
sumber
3

Buka konsol javascript . Anda akan melihat pesan kesalahan di sana. Dalam kasus saya, itu CORS.

Jarekczek
sumber
2

Untuk menjawab pertanyaan mengapa http://127.0.0.1/cd_catalog.xmlberfungsi sementara http://localhost/cd_catalog.xmltidak: Firefox memperlakukan 127.0.0.1 dan localhost sebagai dua domain berbeda.

Tomi Aarnio
sumber
2

Untuk melihat apa masalahnya, ketika Anda mendapatkan kesalahan samar 0 pergi ke ... | Lebih Banyak Alat | Alat Pengembang (Ctrl + Shift + I) di Chrome (di halaman yang memberikan kesalahan)

Baca teks merah di log untuk mendapatkan pesan kesalahan yang sebenarnya. Jika terlalu banyak di sana, klik kanan dan Hapus Konsol, lalu lakukan permintaan terakhir Anda lagi.

Masalah pertama saya adalah, saya menyampaikan header Otorisasi ke layanan web lintas domain saya sendiri untuk browser untuk pertama kalinya.

Saya sudah memiliki:

Access-Control-Allow-Origin: *

Tapi tidak:

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

di header respons layanan web saya.

Setelah saya menambahkan itu, kesalahan nol saya telah hilang dari server web saya sendiri, serta ketika menjalankan file index.html secara lokal tanpa server web, tetapi masih memberikan kesalahan dalam pena kode.

Kembali ke ... | Alat Lainnya | Developer Tools sementara mendapatkan error di codepen, dan dijelaskan dengan jelas: codepen menggunakan https, jadi saya tidak dapat melakukan panggilan ke http, karena keamanannya lebih rendah.

Oleh karena itu, saya perlu menghosting layanan web saya di https.

Mengetahui bagaimana mendapatkan pesan kesalahan yang sebenarnya - tak ternilai harganya!

Maya
sumber
Saya menggunakan pendekatan ini (f12 di chrome) dan ternyata saya mencoba beralih dari https ke http yang diam-diam gagal tanpa memberikan sesuatu yang berguna. PESAN KESALAHAN: VM1152: 1 Konten Campuran: Laman di 'https://mysiteoriginsite' dimuat melalui HTTPS, tetapi meminta titik akhir XMLHttpRequest yang tidak aman 'http://MyDestinationSite/MyService.svc'. Permintaan ini telah diblokir; konten harus disajikan melalui HTTPS.
GrayDwarf
1

Berikut kasus lain di mana status === 0, khusus untuk mengunggah:

Jika Anda melampirkan 'load'event handler ke XHR.upload, seperti yang disarankan oleh MDN (gulir ke bawah ke bagian unggahan 'Pemantauan kemajuan'), objek XHR akan memiliki status=0dan semua properti lainnya akan menjadi string kosong. Jika Anda memasang 'load'penangan langsung ke objek XHR, seperti yang Anda lakukan saat mengunduh konten, Anda akan baik-baik saja (mengingat Anda tidak menjalankan localhost).

Namun, jika Anda ingin mendapatkan data yang bagus di 'progress'event handler, Anda perlu melampirkan handler ke XHR.upload, bukan langsung ke objek XHR itu sendiri.

Saya baru mengujinya sejauh ini di Chrome OSX, jadi saya tidak yakin berapa banyak masalah di sini adalah dokumentasi MDN dan seberapa besar penerapan Chrome ...

ericsoco
sumber
1

Alex Robinson sudah (dan pertama) memberikan jawaban yang benar untuk masalah ini. Tetapi untuk menguraikannya sedikit lebih ...

Anda harus menambahkan header tanggapan HTTP:

Access-Control-Allow-Origin: *

Jika Anda melakukan ini, hasilnya bukan hanya 'mungkin berhasil', tetapi 'akan berhasil'.

NB Yang perlu Anda tambahkan adalah header respons HTTP - jadi Anda hanya dapat melakukan ini di server yang Anda kontrol. Tidak mungkin untuk langsung mengambil http://w3schools.com/XML/cd_catalog.xml dari URL aslinya menggunakan XMLHttpRequest(sesuai pertanyaan OP), karena sumber daya itu tidak (setidaknya, tidak sejak 24 Apr 2015) menyertakan header CORS seperti itu.

http://en.wikipedia.org/wiki/Cross-origin_resource_sharing memberikan info lebih lanjut.

MikeBeaton
sumber
0

Masalah saya yang mirip dengan ini diselesaikan dengan memeriksa kode html saya. Saya memiliki onclickpenangan dalam tombol kirim formulir saya ke suatu metode. seperti ini: onclick="sendFalconRequestWithHeaders()". Metode ini pada gilirannya memanggil ajax seperti milik Anda, dan melakukan apa yang saya inginkan. Tapi tidak seperti yang diharapkan, browser saya tidak menghasilkan apa-apa.

Belajar Dari kerja keras seseorang , saya telah mengembalikan salah di pawang ini, dan diselesaikan. Izinkan saya menyebutkan bahwa sebelum tiba di posting ini, saya telah menghabiskan seluruh akhir pekan 3 hari dan setengah hari di kantor menulis kode penerapan CORS filters,, hal-hal terkait jetty configlainnya jersey and embedded jetty- hanya untuk memperbaiki ini., Berputar semua pemahaman saya sekitarcross domain ajax requests dan hal-hal standar. Sungguh konyol betapa kesalahan sederhana dalam javascript membuat Anda bodoh.

Sejujurnya, saya telah mencoba signed.applets.codebase_principal_support = truedan menulis isLocalHost() **if**. mungkin metode ini perlu diterapkan oleh kami, firefox mengatakan tidak ada seperti itu Sekarang saya harus membersihkan kode saya untuk mengirimkan git patch dengan bersih. Terima kasih untuk seseorang itu.

Siva Tumma
sumber
0

Permintaan browser "127.0.0.1/somefile.html" tidak berubah ke server web lokal, sementara "localhost / somefile.html" mungkin datang sebagai "0: 0: 0: 0: 0: 0: 0: 1 / somefile.html "jika IPv6 didukung. Jadi yang terakhir dapat diproses seperti berpindah dari domain ke domain lain.

Massimo Roscio
sumber
0

Alex Robinson dan bmju memberikan informasi berharga untuk memahami masalah lintas sumber. Saya ingin menambahkan bahwa Anda mungkin perlu membuat panggilan OPTIONS eksplisit dalam kode klien Anda sebelum membuat GET / POST yang diinginkan (mis. Terhadap titik akhir layanan CORS OAuth). Browser / perpustakaan Anda mungkin tidak secara otomatis menangani permintaan OPTIONS. Gruber, ini adalah salah satu kemungkinan jawaban atas pertanyaan Anda.

Tim McConnell
sumber
0

Saya memiliki masalah yang sama (readyState adalah 4 dan status 0) , lalu saya mengikuti pendekatan berbeda yang dijelaskan dalam tutorial ini: https://spring.io/guides/gs/consuming-rest-jquery/

Dia tidak menggunakan XMLHttpRequest sama sekali, sebagai gantinya dia menggunakan metode 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>

dan untuk file publik / hello.js (atau Anda dapat memasukkannya ke dalam kode HTML yang sama secara langsung):

$(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
sumber
2
Anda menyadari bahwa jQuery $.ajax()menggunakan XMLHttpRequestdi dalam, bukan?
Manngo
-1

Saya baru saja mengalami masalah ini karena saya menggunakan 0.0.0.0sebagai server saya, mengubahnya menjadi localhostdan berhasil.

Vad
sumber
-4

Edit: Silakan baca komentar Malvolio di bawah karena pengetahuan jawaban ini sudah ketinggalan zaman.

Anda tidak dapat melakukan XMLHttpRequests lintas domain.

Panggilan ke 127.0.0.1berfungsi karena halaman pengujian Anda berada di 127.0.0.1, dan pengujian lokal juga berfungsi karena, yah ... ini adalah pengujian lokal.

Dua pengujian lainnya gagal karena JavaScript tidak dapat berkomunikasi dengan server jauh melalui XMLHttpRequest.

Sebagai gantinya, Anda dapat mempertimbangkan:

  • XMLHttp-minta server Anda sendiri untuk mengambil konten XML jarak jauh Anda (skrip php, misalnya)
  • Mencoba menggunakan layanan seperti GoogleAppEngine jika Anda ingin tetap menggunakan JavaScript penuh.

Semoga membantu

Gabriel Sprenger
sumber
40
Ini salah. Anda dapat melakukan XMLHttpRequests lintas domain.
Malvolio
1
"Anda tidak bisa" seperti dalam "Anda tidak boleh melakukannya karena itu bukan ide yang bagus"
Gabriel Sprenger
24
- cukup adil, tetapi saya tidak tahu apakah komentar adalah forum terbaik untuk itu. XMLHttpRequests lintas domain memang memiliki beberapa tantangan keamanan tetapi mereka menawarkan semua alat yang diperlukan untuk menangani tantangan tersebut. Selain itu, mereka mengizinkan situs web menawarkan layanan ke situs web lain dengan mudah, menggunakan CDN untuk menyebarkan data, dan menanggapi permintaan pengguna dengan lebih cepat. Jika Anda memiliki pertanyaan spesifik, Anda dapat mengirimi saya pesan, atau lebih baik, posting pertanyaan di sini di SO dan menarik perhatian saya ke sana.
Malvolio
2
@GabrielSprenger: Cross-domain XMLHttpRequestbukan hanya ide yang bagus , ini sangat umum saat ini sehingga TIDAK melakukannya di aplikasi web modern (di luar semacam HelloWorlds) adalah sesuatu yang konyol. Layanan REST eksternal apa pun yang digunakan aplikasi Anda memerlukan lintas domain XMLHttpRequest. Dan itulah mengapa semua hal CORS ditambahkan.
Alexander Abakumov