Ajax readyState is 4 but status 0

By Kyle Dent
April 22, 2010 | Comments: 4

No doubt many of you have run across this before, but it had me scratching my head for a bit. I have some client-side JavaScript code that makes an XMLHttpRequest (or the equivalent on IE) and should get back a simple list of files as a text/plain document. It was all by-the-book, straightforward stuff, but it wasn't working.


if (req.readyState == 4) {
if (req.status == 200) {
alert(req.responseText);
} else {
alert("error getting list of files: " + req.status + ": " +
req.statusText);
}
}

I did not expect to see the error handling code report that the statusText was 'OK' but the status value was 0. I knew the zero value wasn't coming from the server, so I must have done something wrong. If you already know where I tripped myself up, you can reward yourself by skipping the rest of this.

The security of JavaScript running in browsers is a tricky and important business. Even as far back as Netscape 2.0, browsers have not allowed a script loaded from one origin to make requests to another. Meaning, if my browser retrieves JavaScript code from www.example.com, that code can only send network requests to www.example.com. It's referred to as the same-origin policy and is an obvious security measure that undoubtedly mitigates all kinds of mischief. Most everybody learns about it as soon as they start writing client-side JavaScript. You may be surprised to hear that the same-origin policy was the cause of my problem although in my case I was not violating the spirit of the law, but I did trip on the details of it.

My script was hosted on a system called scallop.example.com on the company network, and I had defined the XMLHttpRequest to use that hostname; however, when I loaded the document containing the script in my browser, I used the shortcut non-fully-qualified name and typed in just http://scallop/. So when my justifiably paranoid browser compared the first origin "scallop" to the script's request to "scallop.example.com," they didn't match. Odd that the statusText should contain 'OK' while the status is 0, but there you have it. I was curious so I checked Safari and Internet Explorer too. Safari also set status to 0, but left the statusText blank. IE, on the other hand, prompted me with a message saying "This page is accessing information that is not under its control. This poses a security risk. Do you want to continue?" I said yes, and sure enough the request was allowed to continue successfully.

The same problem could happen to users whose DNS resolver will work with the same shortcut. The fix is what I should have done from the beginning. Instead of defining the URL for the XMLHttpRequest with the hostname, I should have done it like this:


var fileListReqUrl = "http://" + document.domain + "/cgi-bin/file_list";

That takes care of the problem and makes the script more easily portable to other systems as well.


You might also be interested in:

4 Comments

I am a starter in Ajax.
Thank you for the info was getting the same behaviour, now works.

Thanks for sharing, was having the same problem!

Cheers! Very handy!

Yeah, but what about the legitimate case where you have a form data and you really do want to make a cross-domain Ajax-based request? How do you get that done through script--without opening a new window/tab??

News Topics

Recommended for You

Got a Question?