Serving Fonts for Firefox With Fastly

Setting up a CDN to host assets is one of the first performance improvements I make to a production Rails application. The first time I attempted to host assets from a different domain, I quickly realized that Firefox won’t download fonts from a different domain without specific headers.

Nginx Fix

At the time, our system was using Nginx to serve assets that were fronted by a Amazon Cloudfront CDN. In order to make it work with this setup, I had to add to the following to our Nginx configuration:

location ~* \.(ttf|ttc|otf|eot|woff|svg|font.css)$ {
    add_header Access-Control-Allow-Origin *;
    expires 1M;
    access_log off;
    add_header Cache-Control "public";

This added the Access-Control-Allow-Origin header for all fonts and font-related assets.

Enter Fastly

Fast-forward a few months and we’ve taken the next step in serving assets by uploading them to S3. As mentioned in my previous post about setting up a Cloudfront CDN, we’ve also started using Fastly as our CDN.

Fastly’s caching service is really powerful, but can be overwhelming at times. They make heavy use of Varnish, even to the point of allowing you to write your own Varnish configurations if you choose. I’m a Varnish amateur so I’ll go down the GUI route here.

Setting the headers in S3 upon upload would’ve been ideal, but wasn’t possible given the mechanism were were using to upload. Fortunately, Fastly allows you to set custom headers at any point in the caching life cycle.

The Solution

In Fastly, go to Configure -> Content -> Headers -> + New and enter the following:

"Fastly headers"

This configuration will add the Access-Control-Allow-Origin header to all asset responses. But we can do one better than this!

Fastly’s headers can take conditions…knowing I only wanted to add this header to fonts, I clicked Response Conditions on the header I previously added:

"Fastly Conditions"

And entered the following:

"Fastly Condition"

This condition looks at the URL of the incoming request to determine whether it matches any of the following regex conditions: req.url ~ "(ttf|ttc|otf|eot|woff|svg|font\.css)$". If it does, it’ll apply the Access-Control-Allow-Origin header.

Note: Once you’ve made these changes, don’t forget to click the Deploy button, otherwise, you won’t see the new headers.

In Summary

While Fastly can be overwhelming, the power of being able to modify any aspect of the caching stack is valuable. Asset download times have generally been somewhere between 30-50 ms. Cloudfont offered this performance at times, but wasn’t very consistent - some would be 30 ms, and others would take 150 ms. I haven’t noticed this inconsistency with Fastly and would happily recommend their service to anyone looking to improved their caching layer.