Providing Cross Domain access to images and data in Codepen
How come your codepen example doesn’t work when you link to a file on your FTP server? Often times it’s because of CORS, so I thought I’d share a few easy ways of dealing with this.
Cross Domain/Origin, CORS /Access-Control-Allow-Origin/whatever-you-call-it can be a frustrating stumbling block for front end developers who simply want to use or share resources from around the web in their projects.
I recently decided to create a collection of past experiments in Codepen, and quickly came upon this familiar problem when trying to do something as simple as display an image or load a data file with AJAX. Codepen allows you to link to javascripts elsewhere on the web, but what about images, or JSON, or other types of files? How come your codepen example doesn’t work when you link to a file on your FTP server? Often times it’s because of CORS, so I thought I’d share a few easy ways of dealing with this.
I won’t go too in depth about CORS itself (you can read more here if you want to know more), but the gist of it is that, when a server doesn’t know who’s trying to access its data, it will turn them away unless it is specifically told otherwise.
Fix #1: Make a Codepen of your file and link to it
Just want to link to some javascript-ish files like JSON or CSV? Or have a javascript library you want to load that you can’t find a CDN for? Just make a new codepen, copy and paste your data into the JS portion, and copy the URL, adding a .js as the file extension. For example, here’s a pen that just contains some GeoJSON data (for use in mapping / data visualization). And here’s that same pen as data. Because the data comes from Codepen, it’s not cross-origin.
Now here’s me using that data via AJAX within D3.js. You can see I even have a TSV (Tab Separated Values) file in there. I just need to make sure my AJAX request specifies that the .js file it is linking to is actually JSON (or whatever file type you’re intending).
But what about things like images? They can’t intuitively be interpreted as code, and there’s no way within Codepen (that I know of) to specify an image as an external resource. This same Codepen involves me loading a map marker image for use in marking locations on a 3D Globe. Which brings me to…
Fix #2: Use Amazon Web Storage.
Chances are as a coder you’ve already had to deal with AWS / S3 in some way. It’s where some of the biggest, most popular websites around store their files. As a front end dev mostly involved with animation, styling, and data visualization, I haven’t had to deal with it much. But I have an Amazon account! And making an Amazon Web Storage account isn’t much more difficult.
Head to their URL, create an AWS account, and then head into the console, where you can search for S3 (or use this URL) to get into the file storage console.
Make a bucket (folder) for all your codepen files, then click into it and go Permissions > CORS Configuration to make sure that any files you put in this folder can be accessed from Codepen (or wherever else you want to give access to).
If you don’t care what domains access your files (you really should), your CORS header can be as simple as
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Or to make sure traffic comes only from codepen, switch the AllowedOrigin to https://codepen.io
Now, just upload your file, and right click it and select Make Public and you’re good to go! Using S3 to store your static assets is a good idea regardless of whether you’re trying to get around CORS — it’s fast, secure, scalable, it’s distributed to servers by geography, it’s backed up, there’s analytics, all sorts of good stuff.
But if you don’t want to go to all that trouble, you can just use…
Fix #3: Use a proxy
Crossorigin.me is a proxy service, and using it is simple. Take the regular URL to your file, and stick https://crossorigin.me/ in front of it. That’s it! It only works with files under 2mb, it’s not fast, and it only works with GET requests (not POST or PUT). And if you do use it, you are morally obligated to give a little somethin’ somethin’ to the folks who built it =)
Anyway — there are various other workarounds — feel free to comment with your own. Hope it helps you get your codepens up and running. You can find all my experiments here. I’m hoping to add a lot more soon!
Fix #4: Add an .htaccess file to your server
If you have your own server, and it supports htaccess, you can enable apache headers, and then just add an htaccess file wherever you need cross domain access to a file. To do this, ssh into your server and run:
a2enmod headers
service apache2 reload
And then create a file called .htaccess, with the contents:
Header set Access-Control-Allow-Origin "*"
(or a comma sepearated list of whatever domains you want to allow in place of the *)