Merging s-maxage and max-age

1.8k 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 best solutions below

5
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
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
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.