XMLHttpRequest สถานะ 0 (responseText ว่างเปล่า)


107

ไม่สามารถรับข้อมูลด้วย XMLHttpRequest (สถานะ 0 และ responseText ว่างเปล่า):

xmlhttp = XMLHttpRequest ใหม่ ();
xmlhttp.open ("GET", "http://www.w3schools.com/XML/cd_catalog.xml", จริง);
xmlhttp.onreadystatechange = ฟังก์ชัน () 
{
  ถ้า (xmlhttp.readyState == 4)
    การแจ้งเตือน ("สถานะ" + xmlhttp.status);
}
xmlhttp.send ();

มันแจ้งเตือน "สถานะ 0"

สถานการณ์เดียวกันกับคำร้องขอ localhost (cd_catalog.xml ถูกบันทึกเป็นไฟล์โลคัล)

xmlhttp.open ("GET", "http: //localhost/cd_catalog.xml", จริง);

แต่มีคำขอ IP ของ localhost

xmlhttp.open ("GET", "http://127.0.0.1/cd_catalog.xml", จริง);

และด้วยการร้องขอไฟล์ในเครื่อง

xmlhttp.open ("GET", "cd_catalog.xml", จริง);

ทุกอย่างเรียบร้อย (สถานะ 200)

อะไรทำให้เกิดปัญหา (สถานะ = 0) กับคำขอออนไลน์

PS: Live HTTP Headers แสดงว่าทุกอย่างเรียบร้อยทั้ง 4 กรณี:

  HTTP / 1.1 200 ตกลง
  ความยาวเนื้อหา: 4742

PS2: เว็บเซิร์ฟเวอร์ภายใน Apache บน VMWare (โฮสต์ OS Win7, Guest OS Ubuntu, อะแดปเตอร์เครือข่าย - NAT) เบราว์เซอร์ - Firefox


1
หน้าทดสอบของคุณhttp://127.0.0.1มีโอกาสเกิดขึ้นหรือไม่? ;)
Roatin Marth

ใช่. <code> 127.0.0.1/CDCatalogTest.html </code>
arigasa

7
คุณตอบคำถามของคุณแล้ว XMLHttpRequestไม่สามารถส่งคำขอข้ามโดเมนได้ มีวิธีแก้ปัญหาบางอย่างอยู่ ดูที่ jquery เช่น
meze

ใช้ php เพื่อรับไฟล์ วิธีแก้ปัญหาเล็กน้อย: jquery-howto.blogspot.com/2009/04/…

2
@meze: การโทรข้ามโดเมนทำงานร่วมกับ jQuery แต่จะไม่ทำงานกับ JavaScript ธรรมดาได้อย่างไรเนื่องจาก jQuery ถูกนำไปใช้ใน JavaScript มันไม่สมเหตุสมผลสำหรับฉัน jQuery ใช้วิธีแก้ปัญหาที่น่ารังเกียจบางอย่างหรือไม่?
Gruber

คำตอบ:


55

สถานะคือ 0 เมื่อไฟล์ html ของคุณที่มีสคริปต์ถูกเปิดในเบราว์เซอร์ผ่านทางไฟล์ อย่าลืมวางไฟล์ไว้ในเซิร์ฟเวอร์ของคุณ (apache หรือ tomcat อะไรก็ได้) จากนั้นเปิดผ่านโปรโตคอล http ในเบราว์เซอร์ (เช่นhttp: //localhost/myfile.html ) นี่คือวิธีแก้ปัญหา


1
เหตุใดจึงถูกลดคะแนน มันคือเรื่องจริง! คำขอ XHR จากไฟล์: // URL ของไฟล์ในไฟล์ด้วย: // URL มีสถานะ == 0 เมื่อสำเร็จ (ทดสอบกับ FF 24.0.5)
Daniel Roethlisberger

3
ฉันยังได้รับสถานะ == 0 ในความสำเร็จบน Safari เวอร์ชัน 6.1.6
Planar

ฉันมีสถานะ = 0 (แต่สถานะ 200 บนเครือข่าย) กำลังใช้โหลดส่วนเสริมชั่วคราวบน firefox
JobaDiniz

1
ยังคงเป็นคำตอบที่ถูกต้อง การตอบสนอง HTTP คือ 200 สำหรับรีโมตสกีมจริง (http et al.) และ 0 สำหรับไฟล์โลคัล ( file://สกีม) เห็นได้ชัดว่าคุณต้องอนุญาตให้โหลดไฟล์ในเครื่องก่อนโดยปิดใช้งาน CORS
pid

32

สาเหตุของปัญหาของคุณคือการที่คุณกำลังพยายามที่จะทำโทรข้ามโดเมนและจะล้มเหลว

หากคุณกำลังพัฒนา localhost คุณสามารถโทรข้ามโดเมนได้ - ฉันทำตลอดเวลา

สำหรับ Firefox คุณต้องเปิดใช้งานในการตั้งค่าการกำหนดค่าของคุณ

signed.applets.codebase_principal_support = true

จากนั้นเพิ่มสิ่งนี้ในรหัสเปิด XHR ของคุณ:

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

สำหรับ IE ถ้าจำไม่ผิดสิ่งที่คุณต้องทำคือเปิดใช้งานการตั้งค่าความปลอดภัยของเบราว์เซอร์ภายใต้ "เบ็ดเตล็ด→เข้าถึงแหล่งข้อมูลข้ามโดเมน" เพื่อให้ทำงานกับ ActiveX XHR

IE8 ขึ้นไปยังเพิ่มความสามารถข้ามโดเมนให้กับวัตถุ XmlHttpRequest ดั้งเดิม แต่ฉันยังไม่ได้เล่นกับสิ่งเหล่านั้น


8
ในกรณีที่ใคร ๆ ก็ต้องการมันสำหรับ Chrome คุณต้องเปิดอินสแตนซ์ใหม่ (โดยที่ยังไม่ได้เปิด) และใช้--allow-file-access-from-files
TheZ

@TheZ: คุณ 100% หรือเปล่า? ฉันได้ยินมาว่าคุณต้องเรียกใช้อินสแตนซ์ใหม่ของ Chrome พร้อม--allow-file-access-from-filesสวิตช์เท่านั้น แต่คุณไม่จำเป็นต้องปิดอินสแตนซ์อื่น ๆ ที่กำลังทำงานอยู่ทั้งหมด เช่นเดียวกับในกรณีของโหมดไม่ระบุตัวตนของChrome - คุณสามารถใช้งานได้โดยไม่ต้องปิดอินสแตนซ์อื่น ๆ ที่กำลังทำงานอยู่
trejder

ดูเหมือนว่าการสนับสนุนสำหรับ 'UniversalBrowserRead' จะถูกยกเลิกดังนั้นวิธีแก้ปัญหานี้จึงไม่ใช่ตัวเลือก
perilandmishap

นอกจากนี้อาจเกิดขึ้นเมื่อคุณขอหน้า http จากหน้า https (เช่นส่วนขยายในเบราว์เซอร์)
sibvic

ฉันพบปัญหานี้แม้ว่าหน้า html และสคริปต์ AJAX จะอยู่ในโดเมนเดียวกัน แต่น่าแปลกที่มีผลกับสคริปต์บางสคริปต์เท่านั้นโดยเฉพาะสคริปต์ใด ๆ ที่เข้าถึงทรัพยากร MongoDB เบาะแสว่าทำไมถึงเป็นเช่นนี้?
David Edwards

26

ตรวจสอบให้แน่ใจว่าประเภทปุ่มของคุณคือ Button not Submit ซึ่งทำให้เกิดความขัดแย้งของสถานะที่ฉันพบเมื่อเร็ว ๆ นี้


1
มีข้อขัดแย้งเนื่องจากการส่งแบบฟอร์มมีลักษณะการทำงานเริ่มต้นบางอย่างที่คุณต้องป้องกันหากคุณกำลังจัดการกิจกรรมและโทรหาตัวเองด้วย ajax คุณสามารถป้องกันพฤติกรรมเริ่มต้นได้โดยรับเหตุการณ์ในเครื่องจัดการของคุณแล้วโทรไปที่e.preventDefault()
จอร์แดน

20

หากเซิร์ฟเวอร์ตอบสนองต่อวิธี OPTIONS และต่อ GET และ POST (ไม่ว่าคุณจะใช้วิธีใด) โดยมีส่วนหัวดังนี้:

Access-Control-Allow-Origin: *

มันอาจจะใช้ได้ ดูเหมือนว่าใน FireFox 3.5 และ rekonq 0.4.0 เห็นได้ชัดว่าด้วยส่วนหัวดังกล่าวและการตอบสนองครั้งแรกต่อ OPTIONS เซิร์ฟเวอร์กำลังพูดกับเบราว์เซอร์ว่า "ดำเนินการต่อและปล่อยให้คำขอข้ามโดเมนนี้ดำเนินการต่อไป"


3
นี่คือคำตอบที่ใช่! ดูที่en.wikipedia.org/wiki/Cross-origin_resource_sharingสำหรับข้อมูลเพิ่มเติม หากคุณเพิ่มส่วนหัวนี้จะไม่ใช่ "อาจใช้งานได้" แต่ "ใช้ได้ผล" หมายเหตุสิ่งที่คุณต้องเพิ่มคือ HTTP / response / header - ดังนั้นคุณสามารถทำได้บนเซิร์ฟเวอร์ที่คุณควบคุมเท่านั้น จะไม่สามารถดึงข้อมูลw3schools.com/XML/cd_catalog.xmlได้โดยตรงโดยใช้XMLHttpRequest(เช่นตามคำถามเดิม) เนื่องจากทรัพยากรนั้นไม่มี (อย่างน้อย ณ วันที่ 24 เมษายน 2015) รวมส่วนหัว CORS ดังกล่าว
MikeBeaton

14

พิจารณาการหมดเวลาของคำขอด้วย :

เบราว์เซอร์สมัยใหม่ส่งคืนreadyState = 4และ s tatus = 0หากเวลาผ่านไปนานเกินไปก่อนการตอบสนองของเซิร์ฟเวอร์


3
@AndreaSavojardo: คุณมีข้อมูลอ้างอิง (เช่นโพสต์บน MDN) ว่าพฤติกรรมนี้เป็นไปตามมาตรฐานหรือไม่
Alexander Abakumov

@AndreaSavojardo ฉันมี readyState = 4 และ status = 0 และเซิร์ฟเวอร์ไม่ทำงาน แต่การแจ้งเตือนของข้อผิดพลาดแสดงให้ฉันเห็นอย่างรวดเร็ว .... เวลาผ่านไปนานเท่าใดสำหรับ "ขอหมดเวลา"?


4

เปิดคอนโซล JavaScript คุณจะเห็นข้อความแสดงข้อผิดพลาดที่นั่น ในกรณีของฉันมันคือ CORS


3

ฉันประสบปัญหาที่คล้ายกัน ทุกอย่างโอเค "readystate" คือ 4 แต่ "สถานะ" เป็น 0 เป็นเพราะฉันใช้เซิร์ฟเวอร์แบบพกพา Apache PHP และไฟล์ที่ฉันใช้ออบเจ็กต์ "XMLHttpRequest" เป็นไฟล์ html ฉันเปลี่ยนนามสกุลไฟล์เป็น php และปัญหาได้รับการแก้ไขแล้ว


2

เพื่อตอบคำถามว่าเหตุใดจึงใช้http://127.0.0.1/cd_catalog.xmlงาน http://localhost/cd_catalog.xmlไม่ได้: Firefox กำลังปฏิบัติกับ 127.0.0.1 และ localhost เป็นสองโดเมนที่แตกต่างกัน


2

หากต้องการดูว่าปัญหาคืออะไรเมื่อคุณได้รับข้อผิดพลาดที่เป็นความลับ 0 ให้ไปที่ ... | เครื่องมือเพิ่มเติม เครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ (Ctrl + Shift + I) ใน Chrome (บนหน้าที่ระบุข้อผิดพลาด)

อ่านข้อความสีแดงในบันทึกเพื่อรับข้อความแสดงข้อผิดพลาดที่แท้จริง หากมีอยู่ในนั้นมากเกินไปให้คลิกขวาและล้างคอนโซลจากนั้นทำการร้องขอครั้งสุดท้ายอีกครั้ง

ปัญหาแรกของฉันคือฉันส่งส่วนหัวการอนุญาตไปยังบริการเว็บข้ามโดเมนของตัวเองสำหรับเบราว์เซอร์เป็นครั้งแรก

ฉันมีแล้ว:

Access-Control-Allow-Origin: *

แต่ไม่:

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

ในส่วนหัวการตอบกลับของบริการเว็บของฉัน

หลังจากที่ฉันเพิ่มนั้นศูนย์ข้อผิดพลาดของฉันก็หายไปจากเว็บเซิร์ฟเวอร์ของฉันเองเช่นเดียวกับเมื่อเรียกใช้ไฟล์ index.html ในเครื่องโดยไม่มีเว็บเซิร์ฟเวอร์ แต่ก็ยังคงให้ข้อผิดพลาดในปากกาโค้ด

กลับไปที่ ... | เครื่องมือเพิ่มเติม เครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ขณะได้รับข้อผิดพลาดใน codepen และมีคำอธิบายอย่างชัดเจน: codepen ใช้ https ดังนั้นฉันจึงไม่สามารถโทรไปยัง http ได้เนื่องจากความปลอดภัยต่ำกว่า

ฉันต้องโฮสต์บริการเว็บของฉันบน https

รู้วิธีรับข้อความแสดงข้อผิดพลาดที่แท้จริง - ล้ำค่า!


ฉันใช้แนวทางนี้ (f12 ใน chrome) และพบว่าฉันพยายามเปลี่ยนจาก https ไปเป็น http ซึ่งล้มเหลวโดยไม่ได้ให้ประโยชน์อะไรเลย ข้อผิดพลาด: VM1152: 1 ผสมเนื้อหา: หน้าที่'https://mysiteoriginsite' ถูกโหลดผ่าน HTTPS 'http://MyDestinationSite/MyService.svc'แต่ขอปลายทาง คำขอนี้ถูกบล็อก เนื้อหาต้องแสดงผ่าน HTTPS
GrayDwarf

1

นี่เป็นอีกกรณีหนึ่งที่status === 0เฉพาะเจาะจงสำหรับการอัปโหลด:

หากคุณแนบ'load'จัดการเหตุการณ์ที่จะXHR.uploadเป็นข้อเสนอแนะโดย MDN (เลื่อนลงไปที่ส่วนหนึ่งของการอัปโหลด 'การตรวจสอบความคืบหน้า') วัตถุ XHR จะมีstatus=0และทุกคุณสมบัติอื่น ๆ ที่จะเป็นสตริงที่ว่างเปล่า หากคุณแนบ'load'ตัวจัดการโดยตรงกับวัตถุ XHR เช่นเดียวกับที่คุณทำเมื่อดาวน์โหลดเนื้อหาคุณควรจะสบายดี (เนื่องจากคุณไม่ได้ใช้งาน localhost)

แต่ถ้าคุณต้องการที่จะได้รับข้อมูลที่ดีในของคุณ'progress'จัดการเหตุการณ์คุณจะต้องแนบจัดการให้XHR.upload, ไม่ตรงกับวัตถุ XHR ตัวเอง

ฉันได้ทดสอบสิ่งนี้บน Chrome OSX เท่านั้นดังนั้นฉันจึงไม่แน่ใจว่าปัญหานี้เป็นเอกสารของ MDN มากน้อยเพียงใดและการใช้งาน Chrome มีมากน้อยเพียงใด ...


1

Alex Robinson แล้ว (และคนแรก) ให้คำตอบที่ถูกต้องสำหรับปัญหานี้ แต่ถ้าจะอธิบายให้ละเอียดอีกนิด ...

คุณต้องเพิ่มส่วนหัวการตอบกลับ HTTP:

Access-Control-Allow-Origin: *

หากคุณทำเช่นนี้ผลลัพธ์ที่ได้ไม่ใช่แค่ 'อาจได้ผล' แต่ 'ใช้ได้ผล'

หมายเหตุสิ่งที่คุณต้องเพิ่มคือส่วนหัวการตอบกลับ HTTP ดังนั้นคุณสามารถทำได้บนเซิร์ฟเวอร์ที่คุณควบคุมเท่านั้น จะไม่สามารถดึงhttp://w3schools.com/XML/cd_catalog.xmlโดยตรงจาก URL เดิมโดยใช้XMLHttpRequest(ตามคำถามของ OP) เนื่องจากทรัพยากรนั้นไม่มี (อย่างน้อยก็ไม่ใช่วันที่ 24 เมษายน 2015) รวมส่วนหัว CORS ดังกล่าว

http://en.wikipedia.org/wiki/Cross-origin_resource_sharingให้ข้อมูลเพิ่มเติม


0

ปัญหาของฉันคล้ายกับปัญหานี้ได้รับการแก้ไขโดยการตรวจสอบรหัส html ของฉัน ฉันมีonclickตัวจัดการในปุ่มส่งแบบฟอร์มไปยังเมธอด เช่นนี้: onclick="sendFalconRequestWithHeaders()". วิธีนี้จะเรียก ajax เหมือนกับของคุณและทำในสิ่งที่ฉันต้องการ แต่ไม่เป็นไปตามที่คาดไว้เบราว์เซอร์ของฉันไม่คืนค่าอะไรเลย

เรียนรู้จากการทำงานหนักของใครบางคนฉันได้ส่งคืนเท็จในตัวจัดการนี้และแก้ไขแล้ว ผมขอพูดถึงว่าก่อนที่จะเดินทางมาถึงที่โพสต์นี้ผมได้ใช้เวลาวันหยุดสุดสัปดาห์ 3 วันทั้งหมดและครึ่งวันในการเขียนโค้ดสำนักงานการดำเนินการCORS filters, jetty configอื่น ๆjersey and embedded jettyสิ่งที่เกี่ยวข้องกัน - เพียงเพื่อแก้ไขปัญหานี้โคจรรอบ ๆ ความเข้าใจของฉัน.cross domain ajax requestsและมาตรฐานสิ่ง เป็นเรื่องน่าขันที่ข้อผิดพลาดง่ายๆในจาวาสคริปต์ทำให้คุณโง่

ที่จะเป็นจริงฉันได้พยายามและการเขียนsigned.applets.codebase_principal_support = true isLocalHost() **if**เราอาจต้องใช้วิธีนี้ แต่ firefox บอกว่าไม่มีแล้วตอนนี้ฉันต้องล้างรหัสเพื่อส่ง git patch อย่างหมดจด ขอบคุณที่ใครบางคน


0

คำขอเบราว์เซอร์ "127.0.0.1/somefile.html" ไม่เปลี่ยนแปลงไปยังเว็บเซิร์ฟเวอร์ภายในขณะที่ "localhost / somefile.html" อาจมาเป็น "0: 0: 0: 0: 0: 0: 0: 1 / somefile.html "หากรองรับ IPv6 ดังนั้นจึงสามารถประมวลผลจากโดเมนไปยังอีกโดเมนหนึ่งได้


0

Alex Robinson และ bmju ให้ข้อมูลที่มีค่าเพื่อทำความเข้าใจปัญหาข้ามแหล่งกำเนิด ฉันต้องการเพิ่มว่าคุณอาจต้องทำการเรียก OPTIONS อย่างชัดเจนในรหัสไคลเอ็นต์ของคุณก่อนที่จะสร้าง GET / POST ที่ต้องการ (เช่นเทียบกับปลายทางของบริการ CORS OAuth) เบราว์เซอร์ / ไลบรารีของคุณอาจไม่จัดการคำขอ OPTIONS โดยอัตโนมัติ Gruber นี่คือหนึ่งในคำตอบที่เป็นไปได้สำหรับคำถามของคุณ


0

ฉันมีปัญหาเดียวกัน(readyState คือ 4 และสถานะ 0)จากนั้นฉันทำตามวิธีการอื่นที่อธิบายไว้ในบทช่วยสอนนี้: https://spring.io/guides/gs/consuming-rest-jquery/

เขาไม่ได้ใช้XMLHttpRequestเลยเขาใช้วิธี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>

และสำหรับไฟล์สาธารณะ / hello.js (หรือคุณสามารถแทรกลงในโค้ด 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);
   });
 });

2
คุณรู้หรือไม่ว่า jQuery $.ajax()ใช้XMLHttpRequestภายในไม่ใช่เหรอ?
Manngo


-1

ฉันเพิ่งมีปัญหานี้เนื่องจากฉันใช้0.0.0.0เป็นเซิร์ฟเวอร์ของฉันเปลี่ยนเป็นlocalhostและใช้งานได้


-4

แก้ไข:โปรดอ่านความคิดเห็นของ Malvolio ด้านล่างเนื่องจากความรู้ของคำตอบนี้ล้าสมัย

คุณไม่สามารถทำ XMLHttpRequests ข้ามโดเมน

การเรียกให้ใช้127.0.0.1งานได้เนื่องจากหน้าทดสอบของคุณอยู่ที่127.0.0.1และการทดสอบในพื้นที่ก็ใช้งานได้เช่นกัน ... เป็นการทดสอบในพื้นที่

การทดสอบอีกสองครั้งล้มเหลวเนื่องจาก JavaScript ไม่สามารถสื่อสารกับเซิร์ฟเวอร์ที่อยู่ห่างไกลผ่าน XMLHttpRequest

คุณอาจพิจารณาอย่างใดอย่างหนึ่งแทน:

  • XMLHttp ขอเซิร์ฟเวอร์ของคุณเองเพื่อดึงเนื้อหา XML ระยะไกลสำหรับคุณ (เช่นสคริปต์ php)
  • พยายามใช้บริการเช่น GoogleAppEngine หากคุณต้องการให้ JavaScript เต็มรูปแบบ

หวังว่าจะช่วยได้


40
แค่นี้ก็ผิดแล้ว คุณสามารถทำ XMLHttpRequests ข้ามโดเมน
Malvolio

1
"คุณทำไม่ได้" เหมือนใน "คุณไม่ควรทำเพราะมันไม่เคยเป็นความคิดที่ดี"
Gabriel Sprenger

24
- ยุติธรรมเพียงพอ แต่ฉันไม่รู้ว่าความคิดเห็นเป็นฟอรัมที่ดีที่สุดหรือไม่ XMLHttpRequests ข้ามโดเมนมีความท้าทายด้านความปลอดภัยอยู่บ้าง แต่มีเครื่องมือทั้งหมดที่จำเป็นในการจัดการกับความท้าทายเหล่านั้น นอกจากนี้ยังอนุญาตให้เว็บไซต์เสนอบริการให้กับเว็บไซต์อื่น ๆ ได้อย่างง่ายดายใช้ CDN เพื่อเผยแพร่ข้อมูลและตอบสนองต่อคำขอของผู้ใช้ได้เร็วขึ้น หากคุณมีคำถามใด ๆ คุณสามารถส่งข้อความถึงฉันหรือดีกว่าโพสต์คำถามที่นี่ใน SO และดึงดูดความสนใจของฉัน
Malvolio

2
@GabrielSprenger: การข้ามโดเมนXMLHttpRequestไม่เพียง แต่เป็นความคิดที่ดีแต่ปัจจุบันเป็นเรื่องธรรมดามากที่การไม่ทำในเว็บแอปสมัยใหม่ (นอกเหนือจาก HelloWorlds บางประเภท) เป็นสิ่งที่ไร้สาระ บริการใด ๆ REST XMLHttpRequestภายนอกที่กินแอปของคุณต้องมีการข้ามโดเมน และนั่นคือสาเหตุที่เพิ่มเนื้อหาทั้งหมดของ CORS
Alexander Abakumov
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.