10
votes

What's the difference between the following three .htaccess rules and when to use each, is there any special use cases that prefers one over the other?:

Header set Cache-Control "max-age=290304000"
Header set Expires "Thu, 15 Apr 2020 20:00:00 GMT"
ExpiresDefault "access plus 10 years"
2

2 Answers

7
votes

Header is a directive of mod_headers that allows to modify HTTP header fields. In this case Header set effectively sets the mentioned header fields Cache-Control and Expires, so an already existing header field will be overwritten.

The first directive sets the header field Cache-Control with the value max-age=290304000, that describes the freshness lifetime to be 290304000 seconds relative to the response time.

In contrast to that, the second directive sets the header field Expires with the value Thu, 15 Apr 2020 20:00:00 GMT that describes the freshness lifetime with an absolute time value.

Both Cache-Control’s max-age value and Expires expiration time stamp can be transformed to the other:

4.2.1. Calculating Freshness Lifetime

A cache can calculate the freshness lifetime (denoted as freshness_lifetime) of a response by using the first match of the following:

  • ...

  • If the max-age response directive (Section 5.2.2.8) is present, use its value, or

  • If the Expires response header field (Section 5.3) is present, use its value minus the value of the Date response header field, or

  • ...

But if both are present, Cache-Control’s max-age is preferred over Expires:

If a response includes a Cache-Control field with the max-age directive (Section 5.2.2.8), a recipient MUST ignore the Expires field. Likewise, if a response includes the s-maxage directive (Section 5.2.2.9), a shared cache recipient MUST ignore the Expires field. In both these cases, the value in Expires is only intended for recipients that have not yet implemented the Cache-Control field.

Instead of setting these HTTP caching control header fields manually, mod_expires ExpiresDefault directive allows an easy setup for HTTP caching. The freshness lifetime can either be described with an absolute value or with a relative value, either relative to the response time (i.e. access/now) or relative to the modification time of the requested file (i.e. modification). It uses both Cache-Control and Expires.

In this case the third directive sets the default freshness lifetime to be 10 years from the time of response on.

I would use mod_expires for HTTP cache control instead of doing it manually with Header. It is far more convenient, allows both relative and absolute freshness times and uses both Cache-Control and Expires.

3
votes

The first rule adds a max-age entry to Cache-Control. The browser has to refetch the document after the time in seconds given here.

The second and the third rules create expires headers. The browser has to refetch the document at the date given here. And the server has to do some calculations.

Note that the second rule forces a refresh for all browsers and all resources at the same time, while the third and the last rule invalidate the browser cache depending on the request time. You will see the difference if you have a site with much traffic: You will probably get a dramatic peak at 15 Apr 2020. :)

As a rule of thumb: Use max-age. It is very good supported and you don’t have the chance to create an invalid date. Additionally, it’s shorter.

Further reading:

10 URLs authoritatively stated they are expired (and probably mummified) by using an expiry of "01 jan 0001".