Subject: Behaviour of Date and Age Headers on Proxy Revalidate

From: Boris Nikolaus <[email-masked]>
Date: Mon, 23 Jan 2006 15:34:05 +0000

RFC2616 states that

    the Age response-header field conveys the sender's estimate of the
    amount of time since the response (or its revalidation) was
    generated at the origin server

but that
    
    the Date general-header field represents the date and time at
    which the message was originated,

leaving out the behaviour for a proxy after a revalidation for the
Date header.  This leaves two possibilities:

a) The Date represents the time of the original message:

   This is the behaviour of squid 2.5, but looks very weird for
   some objects to me:

   Assume an object has "Cache-Control: max-age=60" and the object is
   queried periodically using a proxy:

   t+0   Object is requested the first time, proxy requests it from
         the web server and forwards the response:
         -> Date: D, no Age
   t+25  Object is queried again, proxy delivers it from its cache:
         -> Date: D, Age: 25
   t+50  Same as above:
         -> Date: D, Age: 50
   t+75  Object reached its max-age, proxy sends a conditional
         request (If-Modified-Since) to revalidate the object;
         web server returns "304 Not Modified" and Date: D+75,
         but as chosen for this case, the web server returns
         -> Date: D, no Age
         because D is the creation date of the cached object and
         no time has been spent since the revalidation.
   t+100 Object is queried again, proxy delivers it from its cache:
         -> Date: D, Age: 25

   What distracts me mostly is that "Date" + "Age" is not monotonic in
   this case because I would like that "Date" + "Age" is an estimate
   for the current time of the clock of the web server (apart from
   network delays).

b) The Date represents the time of the original message or last
   revalidation:

   This would return

   t+0   -> Date: D, no Age
   t+25  -> Date: D, Age: 25
   t+50  -> Date: D, Age: 50
   t+75  -> Date: D+75, no Age
   t+100 -> Date: D+75, Age: 25

   which looks much more convenient to me, but if the object contains
   an Expires response header, this has to be updated, too, whenever
   an object is revalidated and thereby the Date header replaced.

Any comments which version behaves "better"/which behaviour is intended
by the standard? Are there any additional side effects of the two cases?

Boris.

---

From: Alex Rousskov <[email-masked]>
Date: Tue, 24 Jan 2006 15:07:24 -0700

On Mon, 2006-01-23 at 15:34 +0000, Boris Nikolaus wrote:

> Date header.

Pure proxies do not usually originate messages so the above definition
does not leave anything out, I think. The Date header is set by origin
servers. Proxies set Date only if it is missing from the original
message.

>   This leaves two possibilities:
> 

I think (a) is the only possibility. There is nothing weird about the
Date and Age headers you observe if you notice the "or its revalidation"
clause in the Age definition.

>    for the current time of the clock of the web server (apart from

(Date + Age) is not a very meaningful expression in HTTP.
(Request_time - Age) is.

I agree that it may be counter-intuitive.

HTH,

Alex.
P.S. Please note that many proxies do not compute the Age value
correctly (i.e., according to the specs), and the algorithm in the specs
has its own known "inaccuracies".

---

From: Boris Nikolaus <[email-masked]>
Date: Wed, 25 Jan 2006 11:32:49 +0000

> clause in the Age definition.

I just found a section in RFC2616 which would result in (b) being
correct:

    10.3.5 304 Not Modified

    [...]

    The response MUST include the following header fields:
    - Date, unless the omission is required by section 14.18.1
    - [...]
    - Expires, Cache-Control, and/or Vary, if the field-value might
      differ from that sent in any previous response for the same
      variant

    [...]

    If a cache uses a received 304 response to update a cache entry,
    the cache MUST update the entry to reflect any new field values
    given in the response.

According to the last sentence, all the above mentioned headers
have to be updated in the cache (including the Date header), so (b)
should be the correct behaviour (which makes most sense to me).

The only missing part in this description is the update of the
Date header in the cache if it has been omitted in the response due
to section 14.18.1.

Boris.

---

From: Alex Rousskov <[email-masked]>
Date: Wed, 25 Jan 2006 09:36:30 -0700

On Wed, 2006-01-25 at 12:32 +0100, Boris Nikolaus wrote:
> > I think (a) is the only possibility.
>

If the cache updates the cache entry (whatever that means), then the
cache needs to update the Date header as well. However, if the cache
does not update the entry, then it is not required to update Date. In
the latter case, the Age value returned by the cache with subsequent
responses must keep increasing but the Date value will remain the same.

Note that the cache may, in some cases, forward the original 304 back to
the client without modifying it and then switch to generation of its own
304 responses for subsequent responses. And/or you may be talking to
different caches at different times.  This may create Date/Age sequences
that are not as monotonic/predictable as you prefer.

Looking back, I think I gave you a misleading/incorrect answer last
time, confused by the offered choices and an example of a non-HTTP/1.1
compliant cache. I apologize! The server sets Date for each response.
The Date is always the date when the message was generated. However,
there are several messages to consider when we are talking about cache
revalidation:

With respect to the cached entity, the cache has two choices:

 (b) Update Date (and, hence, reset Age)
 (c) Preserve Date (and, hence, increment Age)

With respect to the request that caused revalidation (assuming it was an
IMS request), the cache probably has two choices:

 (i) generate a 304 response based on the cached entity (updated or not)
 (ii) forward the original 304 response

When you combine the above choices, add non-predictability of proxy
routes, and add cooperative proxy meshes into the mix, you get
non-monotonic behavior of Date/Age combinations. Add non-compliant
proxies into the mix (many of which do not even bother to set or update
the Age header!), and you get semi-random Date/Age values.

I hope this answer clarifies the situation better than my original
response.

Alex.