• CORS woes on Heroku

    ,

    After spending the past 4 hours attempting to solve what boiled down to a rather simple problem, I figure I’d better blog about it to save someone else the time and effort.

    If you’ve been leveraging Passenger’s new –nginx-config-template command line option to add CORS headers to static assets served from a Rails app hosted on Heroku, and the CORS headers recently disappeared under mysterious circumstances… read on.

    I’ve been using the method described here to add CORS headers to custom fonts served from a Heroku-hosted Rails app that’s proxied by Nginx which handles serving static files. I recently updated to Rails 4.2.2 and suddenly, my custom fonts (.woff and .woff2 files) no longer had CORS headers on them.

    After the aforementioned hours spent scratching my head, I discovered that the latest version of the sprockets gem is generating asset digests that are 64 chars in length, where previously they had been 32. Nginx’s default regexp for identifying requests for static assets assumes the digest will be 32 chars long, like so:

    # Rails asset pipeline support.
    location ~ "^/assets/.+-[0-9a-f]{32}\..+" {
      error_page 490 = @static_asset;
      error_page 491 = @dynamic_request;
      recursive_error_pages on;</code>
    
      if (-f $request_filename) {
        return 490;
      }
      if (!-f $request_filename) {
        return 491;
      }
    }
    

    Changing the regexp to recognize digests that are 64 chars in length immediately solved the problem:

    location ~ "^/assets/.+-[0-9a-f]{64}\..+" {
       ...
    }
    

    I had to laugh after something so stupid and silly cost me a good chunk of my Saturday to debug. But at least it’s working now. My statically served custom fonts have the correct CORS headers and Chrome and Firefox are happy again.


Need help?

I’m an independent software developer available for consulting, contract work, or training. Contact me if you’re interested.


  • Fast Sphinx indexing with foxy fixtures

    Can Sphinx and foxy fixtures place nicely together? Due to the way Sphinx indexing works, foxy fixtures will often slow down the indexing process drastically. This article explains how to overcome this limitation.

  • Printing an array in multiple table columns

    <% @categories.in_groups_of(2).each do |group| %>
      <tr>
      <% group.each do |category| %>
        <td><%=h category.name %></td>
      <% end %>
      </tr>
    <% end %>
    

    What are you staring at? Move along, move along.

  • Smart asset management for Rails plugins

    Many Rails plugins require that certain files like images, CSS, and JavaScript get copied to the public folder during installation. The typical way to do this is add code to install.rb, which then gets executed when you first install the plugin in your Rails project. What happens when the assets in a plugin you’re using change, though? You end up having to manually copy files around anytime the plugin gets updated, which is an extremely error-prone process.

    I extracted asset_copier from an existing Terralien project. It fixes this problem beautifully. Once installed, it keeps the assets in your Rails project synchronized with your plugin. It even deletes assets from the Rails project that have been removed in the plugin.

    To learn more, check out this post. If instant gratification is more your thing, install the gem directly and apply it to your target plugin:

    sudo gem install pelargir-asset_copier --source=http://gems.github.com
    cd ~/some_rails_project
    script/generate asset_copier some_plugin
    
  • Using routes inside Radius tags

    I’m in the middle of developing a Radiant extension for Terralien. Radius is the tagging language for Radiant, and today I figured out how to use a route from inside a custom tag class.

    A typical Radius tag class might look like this:

    module AwesomeTags
      include Radiant::Taggable
    
      tag "session:logout" do |tag|
        "Logout"
      end
    end
    

    You can see that the hard-coded URL isn’t exactly DRY. I’ve already defined a route for it. Why should I have to hard code it here? The solution:

    module AwesomeTags
      include Radiant::Taggable
      include ActionController::UrlWriter  
      default_url_options[:host] = REGISTRY[:host]
    
      tag "session:logout" do |tag|
        "Logout"
      end
    end
    

    Note that UrlWriter needs to know the host name to base its URLs off of. The host name gets set using the registry pattern. It will be different depending on whether the app is running in development or production mode.

    The same method can be used to reference routes from inside ActiveRecord models.