
  # Set expires headers for assets
  # Assets with a digest (32+ char hex string in filename) get max expires
  # Non-digest assets get 30 mins
  location ^~ /<%= @asset_pipeline_prefix %>/ {
    expires 30m;
    add_header Cache-Control public;
    gzip_static on;

    location ~ "-[0-9a-f]{32,}\." {
      expires max;
    }
  }

<%= @nginx_extra_config %>


  # Set expires headers for assets
  # Assets with a digest (32+ char hex string in filename) get max expires
  # Non-digest assets get 30 mins
  location ^~ /<%= @asset_pipeline_prefix %>/ {
    expires 30m;
    add_header Cache-Control public;
    gzip_static on;

    location ~ "-[0-9a-f]{32,}\." {
      expires max;
      add_header Cache-Control "public, immutable";
    }
  }

<%= @nginx_extra_config %>

Improve refresh speed on some browsers
Improve refresh speed on some browsers

This PR sets the Cache-Control header to "immutable" for certain
assets. This instructs browsers that support the feature that there's
no need to ever check if there's a newer version of an asset.

## Details

Application asset URLs generated by the Rails are "fingerprinted":

> Fingerprinting is a technique that makes the name of a file dependent
on the contents of the file. When the file contents change, the
filename is also changed. For content that is static or infrequently
changed, this provides an easy way to tell whether two versions of a
file are identical, even across different servers or deployment dates.

http://guides.rubyonrails.org/asset_pipeline.html#what-is-fingerprinting
-and-why-should-i-care-questionmark.

For example, our current version of `fonts.css` is named
fonts-5ff8c539134...css.

This system is great because we can tell browsers to cache the file
forever. This is the reason our Cache-Control header is set to the max:

```
$ curl -sI
https://assets.publishing.service.gov.uk/static/fonts-5ff8c53913434afd00
72a480d7cfca67cace4c8d03f6ef96b78a4455728ce745.css | grep Cache-Control
Cache-Control: max-age=315360000, public
```

Well-behaved browsers will request this file at the first request and
use the cached version for the next 10 years.

However, it turns out there's a quirk in some browsers that means that
although the browser knows that the file can be cached, it will still
check with the server if there's a newer version when the user
refreshes the page. You can see this when visiting the GOV.UK homepage.

This is the first page load without any caching:

https://user-images.githubusercontent.com/233676/35106006-ffb403c6-fc64-
11e7-84a3-f3223a9b94d6.png

Any subsequent refresh will looks like this:

https://user-images.githubusercontent.com/233676/35106013-05bb38b6-fc65-
11e7-84cb-137ebe50105b.png

You'll notice that the requests are "cached" and the server returns a
304 status. This means that the browser did make a few dozen requests
to our servers, got a 304 response and used the version from cache.
This is really fast (since the server won't send a lot of data) but
it's not as fast as it could be, which would skipping the requests
altogether.

## Cache-Control immutable

The Cache-Control `immutable` directive will tell the browser that it
shouldn't even bother to check with the servers again. It was thought
up by developers at Facebook last year and since added to Firefox and
Safari (Chrome has another method of avoiding the issue).

https://bitsup.blogspot.co.uk/2016/05/cache-control-immutable.html

There's a nice write-up of it on the HTTP Archive discussion forums,
which is how I found out about it:

https://discuss.httparchive.org/t/cache-control-immutable-a-year-later/1
195

## User impact

It's a bit hard to predict the user impact. What we know is that over
the last 3 months there have been about 1.2 million requests per day
with the 304 status code:

https://user-images.githubusercontent.com/233676/35106136-5b1827d8-fc65-
11e7-91ff-43c1600faa6c.png

https://manage.fastly.com/stats/service/2opfEM1XAHh3YHpqTBxP37/in/all/fr
om/1508251260000/to/1516200060000/by/hour

The header is only supported by certain browsers, and will only be
added for things that are fingerprinted, so I don't expect a massive
decrease in requests, but for some users the site will likely be faster.

## Testing

I've tested this by hand-editing `/etc/nginx/sites-available/static` on
a frontend box in integration and restarting nginx.

```
$ curl -sI
https://assets-origin.integration.publishing.service.gov.uk/static/fonts
-5ff8c53913434afd0072a480d7cfca67cace4c8d03f6ef96b78a4455728ce745.css |
grep Cache-Control
Cache-Control: max-age=315360000
Cache-Control: immutable, public
```

This is the result in Firefox, showing that the cached versions are now
being used:

https://user-images.githubusercontent.com/233676/35106205-8742124c-fc65-
11e7-872b-96ebfb60713e.png
