Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect if ajax error is Access-Control-Allow-Origin or the file is actually missing

My question is NOT about how to solve the Access-Control-Allow-Origin issues. This errors will happen sometimes when performing requests, and other times the url's might be outdated. But I want to print different messages for the user depending on the different errors.

Currently I have the following code:

$.ajax(
{
    url: link,
    type:'HEAD',
    timeout: 2000,
    error: function(request, status, message)
    {
        console.log('ajax error');
        console.log(request);
        console.log(status);
        console.log(message);
        openPopUp("There was an error accessing the image. It can be because the address is invalid, "+
            "or because the server where the image is stored is not allowing direct access to the images.");
    },
    success: function()
    {
        // More stuff here
    }
});

Looking at the console it's easy to see if the file was actually missing, or if it was an Access-Control problem. But i'd like to print out two different messages to the user saying exactly what the problem was. Looking at the variables in error: function(request, status, message) they do not change, both cases result in a 404 error. Is there some other was to do this so that I can know what the problem was?

Thank you in advance for the attention.

like image 486
user2104806 Avatar asked Apr 08 '14 23:04

user2104806


People also ask

What do you know if you get an Access-Control allow Origin error?

This error occurs when a script on your website/web app attempts to make a request to a resource that isn't configured to accept requests coming from code that doesn't come from the same (sub)domain, thus violating the Same-Origin policy.

How do I know if Ajax code is working?

ajax() : $. ajax({ type: 'POST', url: 'page. php', data: stuff, success: function( data ) { }, error: function(xhr, status, error) { // check status && error }, dataType: 'text' });

How do I fix CORS header Access-Control allow Origin missing?

If the server is under your control, add the origin of the requesting site to the set of domains permitted access by adding it to the Access-Control-Allow-Origin header's value. You can also configure a site to allow any site to access it by using the * wildcard. You should only use this for public APIs.


1 Answers

Your browser console shows you

XMLHttpRequest cannot load http://www.google.com/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://mysite.com' is therefore not allowed access.

but you cannot access this information yourself with JavaScript alone. When a browser detects a CORS violation, it will discard the header information as a matter of protocol.


One solution that works is to inspect the response headers using server-side code and pass the results back to your client page. For example, if the ajax request fails, you could call this script (let's call it cors.php) and know for certain if it contains "Access-Control-Allow-Origin" or not.

Example:

cors.php?url=http://ip.jsontest.com
cors.php?url=http://www.google.com

returns

Access-Control-Allow-Origin: *
None

Thus, you can do the following in your JavaScript code:

$.ajax({
  url: "http://www.google.com",
  timeout: 4000,
  statusCode: {
    404: function() {
      // Simple not found page, but not CORS violation
      console.log(this.url + " not found" );
    }
  }
})
.fail(function(jqXHR, textStatus) {
   // Empty status is a sign that this may be a CORS violation
   // but also check if the request timed out, or that the domain exists
   if(jqXHR.status > 0 || jqXHR.statusText == "timeout") {
      console.log("Failure because: "+jqXHR.status+" "+jqXHR.statusText+" error"); 
      return;
   }

   // Determine if this was a CORS violation or not
   console.log("Checking if this is a CORS violation at - " + this.url);
   $.ajax({
      url: "http://myserver.net/cors.php?url=" + escape(this.url),
   })
   .done(function(msg) {
      // Check for the Access-Control-Allow-Origin header
      if(msg.indexOf("Access-Control-Allow-Origin") >= 0) {
        console.log("Failed bacause '" + msg + "'");
      } else {
        console.log("Failed bacause of CORS violation");
      }
   });
})
.done(function(msg) {
  // Successful ajax request
  console.log(msg);
}); /* Drakes, 2015 */

Customize this PHP script for your own needs:

<?php 
/* cors.php */

$url = $_GET["url"];
if(isset($url)) {
    $headers = getHeaders($url, "Access-Control-Allow-Origin");
    header("Access-Control-Allow-Origin: *"); // Allow your own cross-site requests
    echo count($headers) > 0 ? $headers[0] : "None";
}

// Get the response headers, only specific ones
function getHeaders($url, $needle = false) {
    $headers = array();
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_VERBOSE, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'HEAD'); // Only get the headers
    curl_setopt($ch, CURLOPT_HEADER, true);
    curl_setopt($ch, CURLOPT_NOBODY, true);
    curl_setopt($ch, CURLOPT_HEADERFUNCTION, function($curl, $header_line) use(&$headers, $needle) {
        if(!$needle || strpos($header_line, $needle) !== false) {
            array_push($headers, $header_line);
        }
        return strlen($header_line);
    });
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_exec($ch); 
    return $headers;
} /* Drakes, 2015 */
like image 200
Drakes Avatar answered Oct 09 '22 13:10

Drakes