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


  • Amending git commits

    Git is a wonderful SCM with some very powerful features. But as a programmer, it’s very easy to aquire a rudimentary working knowledge of Git and never learn anything more. For example, how would we fix our repository if we committed the wrong piece of code? What if our commit had an error in it? How do we fix things without reverting or introducing a second commit?

    It turns out this is very easy to do. The latest versions of Git have an amend command. Amend lets us alter the last commit we made. All that’s necessary is for us to arrange our working directory the way we want the last commit to look and then execute:

    git commit --amend
    

    This will update the most recent commit based on the state of our working directory. For example, say we changed our README file in the last commit and accidentally introduced a typo. To fix the last commit, we would edit the README again, git add the change, and instead of running git commit which would create a second commit, we run git commit --amend which patches the last commit. This can be repeated as many times as necessary.

    Note that rewriting history like this can have serious implications if you’ve already published the most recent commit. But if you’re the only developer using the repository, or if you haven’t published yet, this can be a great way to fix minor mistakes without introducing an entirely new commit.

    You can read more about amend in the documentation.

  • Quote of the Week: Jack O’Neill

    “Hammond is insisting SG-1 needs a socio-political nerd to offset our overwhelming coolness.” — Jack O’Neill, Stargate SG-1

  • Quote of the Week: Sgt. Elias

    “I love this place at night. The stars… there’s no right or wrong in them. They’re just there.” — Sgt. Elias, Platoon

  • Drop seconds when querying MySQL timestamps

    One of the Rails apps I’ve been working on formats times as HH:MM in the view. No seconds are displayed. This is a pretty common way to format things. When doing timestamp comparisons in SQL, however, the seconds are taken into account. This is bad since it can cause discrepancies in the view.

    For example, say I have a table of records with created_at timestamps. My view displays all records with timestamps equal to or before the current time. Let’s assume the current time is 15:00:00 precisely and I happen to have a record with a timestamp of 15:00:00 in the database. The SQL comparison would work fine in this case.

    SELECT * FROM records WHERE created_at <= "2010-06-25 15:00:00"
    => 1 row in set
    

    What if the timestamp in the database is 15:00:03 though? Let’s run the query again.

    SELECT * FROM records WHERE created_at <= "2010-06-25 15:00:00"
    => Empty set
    

    Since 15:00:03 is greater than the current time of 15:00:00, the record doesn’t get returned. This would be fine if we were displaying seconds in the view, but we’re not. From the user’s perspective, the timestamp on the record is still 15:00 and should appear in the view since it’s equal to the current time. But it doesn’t.

    One way to fix this would be to handle the time comparisons in Ruby. This is certainly a legitimate option. For this particular project, though, performance was a big issue. (And we all know that Rails can’t scale.) I needed a way to continue letting the database handle the comparisons while disregarding seconds.

    The solution I ended up with isn’t ideal (it relies on a couple of functions built into MySQL) but it works fine and runs fast:

    SELECT * FROM records WHERE (created_at - INTERVAL SECOND(created_at) SECOND) <= "2010-06-25 15:00:00"
    => 1 row in set
    

    The number of seconds is extracted from the created_at timestamp and then subtracted from the timestamp. So if the timestamp was 15:00:03, MySQL subtracts 3 seconds to end up with 15:00:00.

    This solved the comparison problem for me and made my client very happy. Double win.