Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Catching 'Origin is not allowed by Access-Control-Allow-Origin' error

img = new Image();

img.crossOrigin = "anonymous";

try {
    cimg.src = document.getElementById("url").value;
}
catch(err) {
    alert("Cannot access image.Cross-Domain access blocked");
};

So, i want to detect/catch Cross-Domain access blocked error.

After some thought i found out that it src loading is async & thus the catch block wont work. Is there any way to detect the error so i can handle it efficiently?

like image 804
Debanjan Dhar Avatar asked Sep 02 '16 13:09

Debanjan Dhar


People also ask

How do you fix origin is not allowed by Access-Control allow origin?

In that case you can change the security policy in your Google Chrome browser to allow Access-Control-Allow-Origin. This is very simple: Create a Chrome browser shortcut. Right click short cut icon -> Properties -> Shortcut -> Target.

How do I fix a blocked CORS policy?

Use a Chrome extension to add Access-Control-Allow-Origin header into every response. To find one of them, just head over to Chrome Webstore and type in "CORS", dozens will show up in the search result. Or you can install CORS Helper, CORS Unblock or dyna CORS right away.

Why does CORS policy no Access-Control allow origin?

To allow any site to make CORS requests without using the * wildcard (for example, to enable credentials), your server must read the value of the request's Origin header and use that value to set Access-Control-Allow-Origin , and must also set a Vary: Origin header to indicate that some headers are being set ...


2 Answers

As @TamasHegedus commented, the image can still be loaded with the CORS error, but it doesn't allow the image data to be manipulated. That means you can use the canvas to try to manipulate the image and catch any thrown errors.

This technique would work for canvas-supported images. See @Kaiido's answer if you want a simpler alternative using the Image#crossOrigin property. His solution also detects whether the property is supported and uses canvas when necessary.

// Must work in IE9+.

var img = new Image;

img.onload = function() {

    var canvas = document.createElement('canvas');

    // resize the canvas, else img won't be rendered
    canvas.width = img.width;
    canvas.height = img.height;

    // get the canvas rendering context 2d
    var ctx = canvas.getContext('2d');

    // draw the image first
    ctx.drawImage(img, 0, 0);

    try {
        /* get first pixel */
        ctx.getImageData(0, 0, 1, 1);

        /* no error catched – no cors error */
        alert("Cross-domain access available.");

    } catch (e) {
        alert("Cross-domain access blocked.");
    }
};

img.src = 'https://i.stack.imgur.com/Kt3vI.png?s=48&g=1';
like image 196
Klaider Avatar answered Sep 18 '22 22:09

Klaider


In browsers supporting crossOrigin requests, (which should be preferred ones), if you set the crossOrigin to 'anonymous', and try to set your element's src pointing to a file hosted on a improperly set-up server, the load event won't fire, and instead, an error event will.

It is important to understand that in the case of a failed crossOrigin request, the server will answer directly that it doesn't accept the request, so only headers are sent between your user and the distant server, while doing the other way around (first try without the crossOrigin request, then try with), you have to first download entirely* the resource , then download it again with the crossOrigin attribute set...

Same applies for audio, video, and xhr requests.

So one should first set the crossOrigin of cross-origin requests, then if it fails it means that the other hand is not properly configured.

var img = new Image();
if('crossOrigin' in img){
  // an up to date browser
  // make a single crossOrigin request
  img.crossOrigin = 'anonymous';
  img.onerror = handleCORSFailure;
  }
else{
  // for browser that don't support the crossOrigin request
  var ctx = document.createElement('canvas').getContext('2d');
  ctx.width = ctx.height = 1; // no need to use too much memory, 1*1 px is enough
  img.addEventListener('load', function(){
    ctx.drawImage(this,0,0);
    try{
      ctx.getImageData(0,0,1,1);
      }
    catch(e){
      handleCORSFailure(e);
      return;
      }
    });
  }

img.src = 'https://i.stack.imgur.com/Kt3vI.png?s=48&g=1';

function handleCORSFailure(e){
  if(e.target){
    console.log('server not set correctly');
    }
  else{
    console.log("browser doesn't support crossOrigin requests");
    }
 }

-* Actually, only images need to be downloaded entirely, all other resources can be tested before the end.

Ps : in case of same-origin request, the crossOrigin attribute should not hurt, so this check can still be performed.

like image 20
Kaiido Avatar answered Sep 19 '22 22:09

Kaiido