3

I'm trying to get my site to load a few webfonts, and I'd like to configure the reponse headers to tell browsers to cache the font, keep it there, and grab the file directly from the cache instead of sending a request to the server.

Google Webfonts does a great job at this; even when I hard reload in Chrome or Firefox, the font loads directly from cache without even checking if there's a newer version available (it returns a 200 status, with (from cache) displayed in Chrome.

However, when I send my response (I'm using nginx as a web server) with all of the usual cache headers, it fails to do this. It'll be great even getting to the point where the browser won't send a request (and the server sending a 304) on a regular page reload.

Here are Google's headers (from one of their WOFF files) served from cache:

HTTP/1.1 200 OK
status: 200 OK
version: HTTP/1.1
access-control-allow-origin: *
age: 13190
alternate-protocol: 80:quic
cache-control: public, max-age=31536000
content-length: 28588
content-type: font/woff
date: Fri, 13 Dec 2013 23:51:45 GMT
expires: Sat, 13 Dec 2014 23:51:45 GMT
last-modified: Thu, 13 Sep 2012 17:47:52 GMT
server: sffe
timing-allow-origin: *
x-content-type-options: nosniff
x-xss-protection: 1; mode=block

Here's one of the responses my server is sending (served 'live'):

HTTP/1.1 200 OK
Server: nginx
Date: Sat, 14 Dec 2013 03:40:37 GMT
Content-Type: font/opentype
Content-Length: 244744
Last-Modified: Mon, 09 Dec 2013 22:35:59 GMT
Connection: keep-alive
Expires: Sun, 14 Dec 2014 03:40:37 GMT
Cache-Control: max-age=31536000
Access-Control-Allow-Origin: *
Cache-Control: public, max-age=315360000
Accept-Ranges: bytes

(I realize that there are 2 Cache-Control headers, but according to spec, that should be fine? The first one is nginx's, the second one I added manually to add 'public').

What is causing the big difference in behaviour between the two responses?

Alfred Xing
  • 4,406
  • 2
  • 23
  • 34
  • See http://stackoverflow.com/a/1285367/2075420 – MeNa Dec 17 '13 at 08:41
  • @MeNa Thanks! My server response has both, and it does indeed serve 304 responses, but is the 304 really required? Why can't the browser just pull it from cache instead of pining my server for a 304 (until the expires date)? – Alfred Xing Dec 18 '13 at 04:08
  • Because of the browser must be sure that the data doesnt modified, he ensure it by 304 req. The concept of caching must take in account a case that the cached object is non-updated and irrelevant (Things are dynamic inherently..). – MeNa Dec 18 '13 at 08:33

1 Answers1

2

I am not overly hip on this stuff, but do have a little experience in configuring web servers. I decided to take a quick look at your issue and I found information on the nginx website that might be useful.

http://nginx.org/ru/docs/http/ngx_http_headers_module.html

But, the main thing I saw was that the nginx responce isn't sending the "Age" header.

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

Here is the main exerpt from w3c:

14.6 Age

  The Age response-header field conveys the sender's estimate of the
  amount of time since the response (or its revalidation) was
  generated at the origin server. A cached response is "fresh" if
  its age does not exceed its freshness lifetime. Age values are
  calculated as specified in section 13.2.3.

       Age = "Age" ":" age-value
       age-value = delta-seconds

  Age values are non-negative decimal integers, representing time in
  seconds.

  If a cache receives a value larger than the largest positive
  integer it can represent, or if any of its age calculations
  overflows, it MUST transmit an Age header with a value of
  2147483648 (2^31). An HTTP/1.1 server that includes a cache MUST
  include an Age header field in every response generated from its
  own cache. Caches SHOULD use an arithmetic type of at least 31
  bits of range.

Sending the "Age" header will probable solve your problem. Good luck!

drankin2112
  • 4,715
  • 1
  • 15
  • 20
  • I tried adding a manual `Age:0` header, but that didn't work... Nginx can't automatically generate age headers anyway. Thanks for the answer though! – Alfred Xing Dec 24 '13 at 04:02
  • 1
    if you manually send Age:15000, then at least you'll know if that's it. 15000 would be 5 hours. I'm pretty sure a 0 means that the browser should refresh the page. – drankin2112 Dec 24 '13 at 04:09