Cross-Origin Resource Sharing bypass

I was coding some Three.js scenes earlier and encountered the following error in Chrome (v27):

Cross-origin image load denied by Cross-Origin Resource
Sharing policy

It happened when I was trying to load an image from a file to use as a texture for a material I wanted to apply to a mesh.  Basically, I wanted my plane to have a grass texture.

THREE.ImageUtils.loadTexture('images/grass.jpg')

Even though both the .html and the .jpg were in the same location (both local, same folder) the error occurred.  Whilst the error, then, makes no sense, it is however ‘working as intended’.  This is, it seems, a security ‘feature’ that is implemented in many browsers, not just Chrome.

Now, I didn’t want to downgrade the security of my browser by launching it as suggested by some:

chrome --allow-file-access-from-files

and I didn’t want to fire up a web server of any kind just for one placeholder texture, as suggested by others:

How to run things locally

Basically, I was in a lazy mood and just wanted a simple security bypass.  🙂  If you do too then the following approach may be of interest…

In essence, we’re going to turn a binary image into text, store that text in a .js file, and then link that external javascript file into our project page.

  • goto: http://dataurl.net/#dataurlmaker
  • upload your image file
  • copy the resulting Data URI text which looks like: “data:image/jpeg;base64…”
  • paste it into a new text document
  • use javascript to create an image element from the Data URI:
var grass = new Image();
grass.src = "data:image/jpeg;base64...";
  • save the document in your project folder somewhere: “images/grassData.js”
  • link to that external javascript file in the <head> of your project page:
<script src="images/grassData.js"></script>
  • create a new Three.js texture using that image element:
var grassTexture = new THREE.Texture(grass);
grassTexture.wrapS = THREE.RepeatWrapping;
grassTexture.wrapT = THREE.RepeatWrapping;
grassTexture.repeat.x = grassTexture.repeat.y = 32;
grassTexture.needsUpdate = true;
  • add the texture to a mesh:
var terrain = new THREE.Mesh(
  new THREE.PlaneGeometry(x,y,x*res,y*res),
  new THREE.MeshLambertMaterial({ map: grassTexture });
);

…and you’re done.  No error.  🙂

Note that this is not intended as a permanent solution to the ‘problem’.  It’s a quick hack to save you some time.  When you deploy your website you want to make sure you’re loading images into textures the normal way to take advantage of caching and smaller file sizes.

Also note that some browsers have rather small limits (32k-ish) on the size of Data URIs, but Chrome/Safari don’t seem to care how large it is.  My grass data was 2.3MB in size and loaded without a hitch.  Just something to look out for if you’re using one of the other browsers.

Enjoy!

Advertisements
This entry was posted in Stuff and tagged , , , , , . Bookmark the permalink.

4 Responses to Cross-Origin Resource Sharing bypass

  1. romaincarpentier says:

    Thank you you saved my life with this code lol
    Here is a better site for base64 encoding : http://websemantics.co.uk/online_tools/image_to_data_uri_convertor/

    Bye, and thx

    • Tim says:

      That converter has a 32kB limit but if your image is only small it will work just fine as well. I’m glad you liked the hack.

  2. Sherry says:

    Awesome post! Thanks so much 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s