Merging s-maxage and max-age

1.7k views Asked by At

I currently have this in my htaccess.

<IfModule mod_headers.c>
  Header set Cache-Control 's-maxage=604800'
</IfModule>
<IfModule mod_expires.c>
  ExpiresActive On
  ExpiresByType text/html A86400
</IfModule>

HTTP headers will show as...

Cache-Control: s-maxage=604800
Cache-Control: max-age=86400
Expires: Wed, 18 Dec 2013 03:51:18 GMT

How do I merge s-maxage and max-age so that it will show as:

Cache-Control: max-age=86400, s-maxage=604800

I've tried using Header set, append, merge and add but nothing works. It seems that ExpiresActive On will automatically include Cache-Control: max-age to the headers.

3

There are 3 answers

5
Jon On

According to the manual, ordering is important. Try re-ordering the two directives and using merge to prevent any duplicates:

<IfModule mod_expires.c>
  ExpiresActive On
  ExpiresByType text/html A86400
</IfModule>
<IfModule mod_headers.c>
  Header merge Cache-Control 's-maxage=604800'
</IfModule>
0
Matthias M On

If you use Header edit you can add the s-maxage header depending on the max-age header:

ExpiresByType text/html A86400
ExpiresByType text/xml A86401

Header edit Cache-Control ^(max-age=86400)$ "$1; s-maxage=604800"

Result: s-maxage is only added for text/html

0
AndrewF On

The simple answer is that there may not be an easy way to join your two headers, but it doesn't actually matter. Semantically there is no difference between this form:

Cache-Control: s-maxage=604800
Cache-Control: max-age=86400

and this form:

Cache-Control: s-maxage=604800, max-age=86400

RFC 7234 § 5.2 defines the Cache-Control header field value as a list of directives defined in a specific form:

Cache-Control   = 1#cache-directive

cache-directive = token [ "=" ( token / quoted-string ) ]

That form is subject to this HTTP rule from RFC 2616 § 4.2:

Multiple message-header fields with the same field-name MAY be present in a message if and only if the entire field-value for that header field is defined as a comma-separated list [i.e., #(values)]. It MUST be possible to combine the multiple header fields into one "field-name: field-value" pair, without changing the semantics of the message, by appending each subsequent field-value to the first, each separated by a comma. The order in which header fields with the same field-name are received is therefore significant to the interpretation of the combined field value, and thus a proxy MUST NOT change the order of these field values when a message is forwarded.

(Note that the #(values) grammar is defined in § 2.1)

Therefore, if a client is treating those two varieties differently, it is in violation of HTTP/1.1.

In fact, there is a chance that what you are seeing as two headers is actually being sent to the client as a single conjoined header line, but your viewer or output is keeping the directives split into two for display.