Value of "Expires" header differ for caching and content serving servers

Ryan Malayter malayter at
Thu Apr 7 23:54:32 MSD 2011

On Thu, Apr 7, 2011 at 7:15 AM, Maxim Dounin <mdounin at> wrote:
> Hello!
> On Wed, Apr 06, 2011 at 06:47:10AM -0400, i.s.ivanov2 wrote:
>> I have a following servers structure:
>> content.server contains an Apache instance, which processes one simple
>> PHP script. On the same node Nginx is set as a caching proxy to that
>> Apache.
>> caching.server contains Nginx with proxy_cache directive, with upstream
>> set to content.server
>> Php script generates an XML file, that has a lifetime of 30 minutes.
>> This is achieved by setting headers in PHP code: "Cache-Control:
>> max-age=1800", "Date: now()" and "Expires: now()+1800seconds".
>> content.server serves the cached file correctly:
>> >   Date      Wed, 06 Apr 2011 09:50:49 GMT
>> >   Cache-Control     public, must-revalidate, max-age=1800
>> >   Expires   Wed, 06 Apr 2011 10:14:25 GMT
>> >   Etag      26ee7051c360ee28d2a5697fb2b97a03
> This doesn't actually correct: Cache-Control max-age and Expires disagree.
> According to max-age, document should expire at 10:20:49, while
> expires set to 10:14:25.
> Unless configured to ignore some headers (with
> proxy_ignore_headers directive) nginx will use first relevant
> header it sees to actually expire cached document, Cache-Control
> max-age in this case.

Really? That behavior would seem to be at odds with the HTTP 1.1
specification. From RFC 2616 section 14.9.3:

"If a response includes both an Expires header and a max-age
directive, the max-age directive overrides the Expires header, even if
the Expires header is more restrictive"

As almost all origin servers send both Expires and Cache-Control in
their default configurations, with the Expires header coming first,
wouldn't nginx end up doing the wrong thing most of the time?

More information about the nginx mailing list