Cache-Control headers repeated; valid or not? (Nginx)

Peter Bengtsson picture Peter Bengtsson · Jan 21, 2011 · Viewed 23.1k times · Source

I've got a resource in my Nginx that is configured like this:

location ~ foo\.js$ {
    add_header Cache-Control public;
    expires 1d;
}

If I open this with Firebug and look at the headers it shows this:

Cache-Control   max-age=86400, public

The site is using HTTPS so I want to make sure I get it right because apparently browsers don't cache it unless it's max-age>0 AND public. See this

But what happens with my Nginx when I use curl -Ik https://... is that it says:

...
Expires: Sat, 22 Jan 2011 18:23:36 GMT
Cache-Control: max-age=86400
Cache-Control: public
...

It repeats the Cache-Control header! Clearly Firebug doesn't mind. But is it right?

Is there a perhaps a better way to set Expires and Cache-Control (with public) in one just two lines?

Answer

jaredjacobs picture jaredjacobs · Mar 9, 2011

Yes, it's valid and equivalent to use multiple Cache-Control headers.

From the HTTP 1.1 spec:

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.

It's easy to verify that this provision applies to the Cache-Control header because of how it's defined:

Cache-Control = "Cache-Control" ":" 1#cache-directive

To understand how to interpret the line above, see the spec's notational conventions. The 1# means "a comma-separated list of one or more".