Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
825 views
in Technique[技术] by (71.8m points)

ajax - How to Detect Cross Origin (CORS) Error vs. Other Types of Errors for XMLHttpRequest() in Javascript

I'm trying to detect when an XMLHttpRequest() fails due to a Cross Origin Error as opposed to a bad request. For example:

    ajaxObj=new XMLHttpRequest()
    ajaxObj.open("GET", url, true); 
    ajaxObj.send(null);

Consider 4 cases for url:

Case 1: url is a valid address where access-control-allow-origin is properly set

  • Example: http://192.168.8.35 where I have a server with Access-Control-Allow-Origin: * set in the header
  • This is easy to detect as ajaxObj.readyState==4 and ajaxObj.status==200

Case 2: url is an invalid address at an existing server

  • Example: http://xyz.google.com where the server responds but it is not a valid request
  • This results in ajaxObj.readyState==4 and ajaxObj.status==0

Case 3: url is to a non-existing server ip address

  • Example: http://192.168.8.6 on my local network where there is nothing to respond
  • This results in ajaxObj.readyState==4 and ajaxObj.status==0

Case 4: url is a valid address where access-control-allow-origin is NOT set

  • Example: http://192.168.8.247 where I have a server without Access-Control-Allow-Origin: * set in the header
  • This results in ajaxObj.readyState==4 and ajaxObj.status==0

The problem is: How do I differentiate Case 4 (access-control-allow-origin error) and Cases 2&3?

In Case 4, the Chrome debug console shows the error:

XMLHttpRequest cannot load http://192.168.8.247/. Origin http://localhost is not allowed by Access-Control-Allow-Origin.

How do I make that error known in Javascript?

I tried to find some indication in ajaxObj but nothing there seems to be different compared to Case 2&3.

Here is a simple test I used:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>CORS Test</title>
<script type="text/javascript">
function PgBoot()
{
//  doCORS("http://192.168.8.35");   // Case 1
//  doCORS("http://xyz.google.com"); // Case 2
    doCORS("http://192.168.8.6");    // Case 3
//  doCORS("http://192.168.8.247");  // Case 4
}

function doCORS(url)
{
    document.getElementById("statusDiv").innerHTML+="Processing url="+url+"<br>";
    var ajaxObj=new XMLHttpRequest();
    ajaxObj.overrideMimeType('text/xml');
    ajaxObj.onreadystatechange = function()
    {
        var stat=document.getElementById("statusDiv");
        stat.innerHTML+="readyState="+ajaxObj.readyState;
        if(ajaxObj.readyState==4)
            stat.innerHTML+=", status="+ajaxObj.status;
        stat.innerHTML+="<br>";
    }
    ajaxObj.open("GET", url, true); 
    ajaxObj.send(null);
}
</script>
</head>
<body onload="PgBoot()">
<div id="statusDiv"></div>
</body>
</html>

Results using Chrome:

Processing url=http://192.168.8.35
readyState=1
readyState=2
readyState=3
readyState=4, status=200

Processing url=http://xyz.google.com
readyState=1
readyState=4, status=0

Processing url=http://192.168.8.6
readyState=1
readyState=4, status=0

Processing url=http://192.168.8.247
readyState=1
readyState=4, status=0
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

No, there is no way to tell the difference, according the W3C Spec.

Here's how the CORS specification specifies the simple cross-origin request procedure:

Apply the make a request steps and observe the request rules below while making the request.

If the manual redirect flag is unset and the response has an HTTP status code of 301, 302, 303, 307, or 308: Apply the redirect steps.

If the end user cancels the request: Apply the abort steps.

If there is a network error: In case of DNS errors, TLS negotiation failure, or other type of network errors, apply the network error steps. Do not request any kind of end user interaction...

Otherwise: Perform a resource sharing check. If it returns fail, apply the network error steps...

In the case of either a failed network connection or a failed CORS exchange, the network error steps are applied, so there is literally no way to distinguish between the two cases.

Why? One benefit is that it prevents an attacker from inspecting the network topology of a LAN. For example, a malicious Web page script could find the IP address of your router by requesting its HTTP interface and therefore learn a few things about your network topology (e.g., how big your private IP block is, /8 or /16). Since your router doesn't (or shouldn't) send CORS headers, the script learns absolutely nothing.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...