3

nginx expires directive sets 2 headers, Expires and Cache-Control:

Config:

expires 1d;

Headers:

Expires: Tue, 24 Nov 2020 12:51:31 GMT
Cache-Control: max-age=86400

I would like to keep Expires header but also set Cache-Control to public, max-age=86400, immutable. But that produces double Cache-Control headers:

Config:

expires 1d;
add_header Cache-Control "public, max-age=86400, immutable"

Headers:

Expires: Tue, 24 Nov 2020 12:57:53 GMT
Cache-Control: max-age=86400
Cache-Control: public, max-age=86400, immutable

I can not just use add_header Expires ..., because it requires exact time in future, not just number of seconds.

I tried using more_set_headers from ngx_headers_more module, but Cache-Control header set by expires directive is still there.

Is there any way to combine correct Expires header with Cache-Control set to immutable?

3

Duplication of the Cache-Control headers isn't a violation of any W3C standard. According to RFC 2616:

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.

Moreover, nginx is aware about it, trying to set a header which shouldn't contain more than one value with the add_header nginx directive will lead to overwrite that header value rather then adding the second one. So you can safely stay with the

expires 1d;
add_header Cache-Control "public, immutable";

configuration.

3

The Cache-Control: header can appear more than once, provided that the two headers do not try to use the same directives. If they do, that directive is ignored. (RFC 7234 § 4.2.1)

Thus you can let nginx send its header with the max-age directive, and send your own with only the other directives.

The result would be:

Expires: Tue, 24 Nov 2020 12:57:53 GMT
Cache-Control: max-age=86400
Cache-Control: public, immutable

(But if max-age=86400 appeared in both headers it would be ignored.)

It's normal and expected that certain header fields may appear more than once. RFC 7230 § 3.2.1 specifies that recipients may combine them into a single header, but this is not required.

  • Thanks! Can't accept both answers, though. – Selivanov Pavel Nov 23 '20 at 13:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.