rails5 + heroku + cloudfront + fonts
I tried to configure a rails5 app (deployed on heroku) with cloudfront for assets and fonts. I could make it work for the assets, then I tried to add the config for the fonts as well, but I just screwed up everything and none of them works.
At the moment for the assets I get 404 error:
Failed to load resource: xzy.cloudfront/assets/application-12341234.css the server responded with a status of 404 ()
For the prev version when the assets worked but the fonts didn't, I got this error (I don't remember what was the diff between the 2 setup):
Access to Font at 'https://xyz.cloudfront.net/assets/fontawesome-webfont-7dacf83f51179de8d7980a513e67ab3a08f2c6272bb5946df8fd77c0d1763b73.woff2' from origin 'https://xyz.cloudfront.net' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://xzy.herokuapp.com' is therefore not allowed access.
I didn't really understand the problem because I thought I had everything properly configured:
config.action_controller.asset_host = ENV['CLOUDFRONT_URL'] config.static_cache_control = 'public, max-age=31536000'
initializes/cors.rb (added the cors gem)
Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do origins '*' resource '/assets/*', headers: :any, methods: [:get] end end
I likely didn't mess up the basic cloudfront config, because it was working before I started tweaking with the fonts. The behavior path pattern is set to default and it's connected to the herokuapp. The problem could be that the forwarded headers in the behavior are set like this:
Access-Control-Allow-Origin Access-Control-Allow-Methods Access-Control-Allow-Headers Access-Control-Max-Age Origin
As far as I know rails5 works with 12factors out of the box, so I don't have to add
config.serve_static_assets = true if my
RAILS_SERVE_STATIC_FILES env var is set to enabled (which happens automatically with heroku).
What did I miss? How can I make this work again?
Yo Szilard! It's been a while since I've setup Cloudfront especially with fonts.
Did you make any progress on this?
I didn't :(. This (https://github.com/equivalent/scrapbook2/blob/master/archive/blogs/2016-09-cors-rails-assets-cdn-heroku.md) seems to be quiet a resource, but didn't solve the problem with rails 5. If I set the allowed headers to my cloudfront distribution name then I get this error:
Access to Font at 'https://b33ef7kfsqfs9e.cloudfront.net/assets/fontawesome-webfont-7dacf83f51179de8d7980a513e67ab3a08f2c6272bb5946df8fd77c0d1763b73.woff2' from origin 'https://b33ef7kfsqfs9e.cloudfront.net' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value 'https://b33ef7kfsqfs9e.cloudfront.net' that is not equal to the supplied origin. Origin 'https://abcdef-staging.herokuapp.com' is therefore not allowed access.
I have a few workarounds in mind like excluding fonts from cloudfront or uploading fonts to S3 (of course with cloudfront pointing to bucket) and adding the new source path in css files, but I would rather do the proper fix with allowed headers.
I thought I would put my two cents in on this issue. I recently tried to use Font Awesome with Heroku and CloudFront on Rails 5 and faced a similar problem. Here's what I did to get it to work:
if defined? Rack::Cors Rails.configuration.middleware.insert_before 0, Rack::Cors do allow do origins %w[ https://example.com http://example.com https://www.example.com http://www.example.com https://example.herokuapp.com http://example.herokuapp.com ] resource '/assets/*' end end end
I preferred not to leave it wide open and just use the domains I knew I would hit it with.
- select the distribution
- click Distribution Settings
- go to the Behaviors tab
- select the behavior (there will probably be only one)
- Click Edit
- Forward Headers: Whitelist
- Whitelist Headers: Select Origin and click Add >>
- Paste the following into the custom box one at a time and click Add Custom>>
Access-Control-Allow-Origin Access-Control-Allow-Methods Access-Control-Allow-Headers Access-Control-Max-Age
After messing with this for over 6 hours, I think I messed it up even more. The last thing I did that finally made these settings stick was invalidate the CloudFront cache.
You can explicitly invalidate cached assets by going to the CloudFront distribution's Invalidations tab and creating an invalidation for
*. I guess CloudFront cache sticks around longer than I had thought. This step took about 10 minutes. Yours might take less.
Awesome post, thanks for sharing Michael! :D I need to do an episode on Cloudfront sometime.