MidnightJava MidnightJava - 3 months ago 21
Javascript Question

Firefox Does not allow CORS request even when the server returns the appropriate response header

My app makes an ajax request using CORS, which works in Chrome but not in Firefox. I followed the MDN CORS instructions, but it does not work.

Here's an elided view of my code:

var href = ...
var request = new XMLHttpRequest();
request.open('GET', href, true);
request.setRequestHeader("Accept", "application/json");
request.onload = ...
request.onerror = ...
try {
request.send();
} catch (e) {
console.log(e.message);
}


This results in a NS_ERROR_DOM_BAD_URI exception, with message "Access to restricted URI denied" and code = 1012.

The server is responding with
Access-Control-Allow-Origin: http://localhost:13000
which I verified when making the request in Chrome. I'd like to look at the response headers in FF, but the web developer console only shows me the GET requests for the javascript files, and I see no way to examine the headers of the ajax request and response. It would also be nice to verify the pre-flight request, which should result from setting a custom header, but I can't see how to get access to that with the debugger.

Answer

I finally found a solution, which seems to indicate a bug in Firefox.

Although not shown in my example code, the server requires HTTP BASIC authentication, which is provided as follows:

request.open('GET', href, true, username, password);
request.withCrednetials = true;

This is in accordance with the MDN specification for XMLHttpRequest.

While this works for Chrome, with Firefox it results in the ajax request not being sent (at least it doesn't appear in the console or net panes of Firebug) and the send() method throwing an exception which claims that the request is being made to an illegal domain.

The following solution works for FF and Chrome:

var href = ...
var username = ...
var password = ...
var request = new XMLHttpRequest();
request.open('GET', href, true); //do not include credentials, or FF will fail to send the request
request.setRequestHeader("Accept", "application/json");
request.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
request.onload = ...
request.onerror = ...
try {
  request.send();
} catch (e) {
  console.log(e.message);
}

Note that if the username and password are provided as parameters to open(), Firefox fails to send the request and throws an illegal domain exception, even though the credentials were set in the Authorization header.