Using a CDN like AWS Cloudfront helps speed up delivery of static assets to your visitors and reduce the load on your servers. Setting up Cloudfront for your Rails apps is very simple, thanks to gems like asset_sync that work nicely with Rails’ asset pipeline compilation process and S3.
One issue can however be tricky to solve sometimes: CORS blocks.
What is happening?
If your assets are served by a CDN like Cloudfront, they can be served from a domain like
sdf73n7ssa.cloudfront.net
while your app is served on www.myawesomeapp.com
. This triggers CORS blocking in browsers to stop malicious websites fetching nasty resources while browsing a seemingly nice website.
The most common type of this issue is with fonts when you get something like this:
Font from origin 'https://sdf73n7ssa.cloudfront.net' has been blocked from loading by Cross-Origin Resource Sharing policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://www.myawesomeapp.com' is therefore not allowed access.
How to fix it?
When it comes to AWS Cloudfront, the most commonly suggested method is to allow CORS origins on the Cloudfront side. This method involves writing XML configuration code for AWS and uploading it on the S3 side.
There is a better and easier way!
I personally prefer using my DNS subdomains to solve this problem. If my CDN is behind
cdn.myawesomeapp.com
instead of sdf73n7ssa.cloudfront.net
then browsers are not going to freakout and block them as cross domain security problems.
To point your subdomain to your AWS Cloudfront domain go to AWS Cloudfront control panel, select your Cloudfront distribution and enter your CDN subdomain into the Alternate Domain Names (CNAMEs) field. Something like
cdn.myawesomeapp.com
will do.
Now you can go to your DNS provider (like AWS Route 53) and create a CNAME for
cdn.myawesomeapp.com
pointing to sdf73n7ssa.cloudfront.net
.
You can test your new CDN domain by making sure assets served from it are coming from Cloudfront.
curl -I http://cdn.myawesomeapp.com/assets/image.png
should return something like this
HTTP/1.1 200 OK
Content-Type: image/png
Content-Length: 10414
Connection: keep-alive
Date: Mon, 22 Sep 2014 10:06:41 GMT
Last-Modified: Sun, 06 Jan 2013 16:37:19 GMT
ETag: "1c4bef3752c306b9c14a05b4a19d7d79"
Accept-Ranges: bytes
Server: AmazonS3
Age: 1599
X-Cache: Hit from cloudfront
Via: 1.1 a3c44e1caa58818cd22903047dc0faf4.cloudfront.net (CloudFront)
X-Amz-Cf-Id: sEbH-vV6deQra_YQa144RxtwhuJaWSrq-tpdiFxWdUbDbR2DnhoIrQ==
No comments:
Post a Comment