• 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.


  • Quote of the Week: Stephen Jay Gould

    “The absence of fossil evidence for intermediary stages between major transitions in organic design, indeed our inability, even in our imagination, to construct functional intermediates in many cases, has been a persistent and nagging problem for gradualistic accounts of evolution.” — Stephen Jay Gould

  • Dirty date/time attrs in Rails lose their time zone

    Dirty attributes were recently added to Rails and they’re quite useful. However, I ran into a problem where a dirty date/time attribute was losing its time zone information after a save. I was doing a comparison between two dates in a before_update callback like so:

    before_update do
      if started_at.to_s(:abbrev_date) != started_at_was.to_s(:abbrev_date)
        errors.add :started_at, "cannot be set to a different day"
      end
    end
    

    The started_at date was coming back in the Eastern time zone as expected. The started_at_was attribute, which was supposed to reflect the value prior to the update, was coming back as a UTC date/time. I would expect it to be returned in the Eastern time zone too. Apparently, I’m not alone in this assumption because a ticket was opened for this issue last month.

    An official fix hasn’t been made yet, but I got around the problem by calling in_time_zone on my dirty attribute:

    before_update do
      if started_at.to_s(:abbrev_date) != started_at_was.in_time_zone.to_s(:abbrev_date)
        errors.add :started_at, "cannot be set to a different day"
      end
    end
    
  • Quote of the Week: Wendell Barry

    “The disease of modern character is specialization…The specialist system fails from a personal point of view because a person who can do only one thing can do virtually nothing for himself.” — Wendell Berry

  • Things I learned today

    1. Compiling Apache and PHP from scratch in DSO mode is a nightmare
    2. Slicehost’s ability to restore a server image from a backup is incredibly useful
    3. I’m glad I’m a developer and not a sys admin

    That is all.