Ask A Question

Notifications

You’re not receiving notifications from this thread.

rails5 + heroku + cloudfront + fonts

Sean M asked in Gems / Libraries

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:

production.rb

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?

Reply

Yo Szilard! It's been a while since I've setup Cloudfront especially with fonts.

Did you make any progress on this?

Reply

Hey Chris,

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.

This error is super weird because basically says https://b33ef7kfsqfs9e.cloudfront.net != https://b33ef7kfsqfs9e.cloudfront.net.

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.

Reply

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:

Installed rack-cors

gem 'rack-cors'

Configured rack-cors

config/initializers/rack-cors.rb

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.

Configure CloudFront

  • https://console.aws.amazon.com/cloudfront/home#distributions
  • 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.

Reply

Awesome post, thanks for sharing Michael! :D I need to do an episode on Cloudfront sometime.

Reply

Nice stuff, this helped me out alot. Big thanks

Reply

Reply

Thanks! Michael it works.

Reply
Join the discussion
Create an account Log in

Want to stay up-to-date with Ruby on Rails?

Join 81,842+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.

    Screencast tutorials to help you learn Ruby on Rails, Javascript, Hotwire, Turbo, Stimulus.js, PostgreSQL, MySQL, Ubuntu, and more.

    © 2024 GoRails, LLC. All rights reserved.