Subject: #227: HEAD and Caches

From: Mark Nottingham <[email-masked]>
Date: Tue, 7 Feb 2012 15:03:56 +1100

I've been bothered by this text (p2 6.4 HEAD) for a while:

>    The response to a HEAD request is cacheable and MAY be used to
>    satisfy a subsequent HEAD request; see [Part6].  It also MAY be used
>    to update a previously cached representation from that resource; if
>    the new field values indicate that the cached representation differs
>    from the current representation (as would be indicated by a change in
>    Content-Length, ETag or Last-Modified), then the cache MUST treat the
>    cache entry as stale.

A few problems:

1. Since it specifies required cache behaviour, it really should be in p6
2. The second MAY seems to conflict with the MUST
3. Caches can store multiple representations for a resource, so there is no "current representation."

Part of the problem here really is that it's not "updating" any response, but it is potentially invalidating an old one.

To resolve this, we could construct a requirement that refers to p6 2.7 ("Caching Negotiated Responses") to identify the correct response to compare to and (potentially) invalidate. 

However, I wonder if a) this is widely implemented, and b) the complexity is worth it. 

I.e., we could alternatively just remove everything after the first sentence (i.e., treat the second MAY as primary, and therefore make the whole thing redundant).

Thoughts?

<http://trac.tools.ietf.org/wg/httpbis/trac/ticket/227>

--
Mark Nottingham   http://www.mnot.net/

---

From: Amos Jeffries <[email-masked]>
Date: Tue, 07 Feb 2012 19:04:25 +1300

> 3. Caches can store multiple representations for a resource, so there is no "current representation."

My reading is that there is an erroneous ";" in the middle of the second 
sentence and "current" is the origins viewpoint of current.

> I.e., we could alternatively just remove everything after the first sentence (i.e., treat the second MAY as primary, and therefore make the whole thing redundant).

Its useful that a HEAD 200 be treated identically to how the equivalent 
GET 200 response would have regarding invalidation and content 
negotiation details. The absence of a body seems not particularly 
relevant to the act of or reasons for invalidation. The presence of a 
body is just a performance edge GET conditionals have over HEAD.

The paragraph does seem like a convoluted way of saying that though.

IMHO changing that second paragraph to "SHOULD invalidate" and 
referencing the negotiation section for the what/how/when bits is the 
right thing to do, even if not implemented very widely right now. The 
origins HEAD result having changed is a very clear sign that the cached 
representation is not really useful now anyway.

AYJ

---

From: Mark Nottingham <[email-masked]>
Date: Mon, 13 Feb 2012 15:45:42 +1100

Proposal --

Old: 

  The response to a HEAD request is cacheable and MAY be used to satisfy a
  subsequent HEAD request; see [Part6]. It also MAY be used to update a
  previously cached representation from that resource; if the new field values
  indicate that the cached representation differs from the current
  representation (as would be indicated by a change in Content-Length, ETag or
  Last-Modified), then the cache MUST treat the cache entry as stale.
   
New:   

The response to a HEAD request is cacheable; it MAY be used to satisfy
subsequent HEAD requests. 

If the Content-Length, ETag or Last-Modified value of a HEAD response differs
from that in the selected GET response (as per [ref to p6 2.7]), the cache
MUST consider that selected response to be stale.

On 07/02/2012, at 5:04 PM, Amos Jeffries wrote:

> My reading is that there is an erroneous ";" in the middle of the second sentence and "current" is the origins viewpoint of current.
> 
> 
>> 
> Its useful that a HEAD 200 be treated identically to how the equivalent GET 200 response would have regarding invalidation and content negotiation details. The absence of a body seems not particularly relevant to the act of or reasons for invalidation. The presence of a body is just a performance edge GET conditionals have over HEAD.
> 
> IMHO changing that second paragraph to "SHOULD invalidate" and referencing the negotiation section for the what/how/when bits is the right thing to do, even if not implemented very widely right now. The origins HEAD result having changed is a very clear sign that the cached representation is not really useful now anyway.
> 
> AYJ
> 
>> 
>>

---

From: Amos Jeffries <[email-masked]>
Date: Tue, 14 Feb 2012 02:31:53 +1300

> MUST consider that selected response to be stale.

+1.

AYJ

---

From: Henrik Nordström <[email-masked]>
Date: Thu, 16 Feb 2012 08:25:01 +0100

> subsequent HEAD requests. 

You just lost the property of HEAD updating GET responses. This is a
very intentional property.

HEAD response == GET response minus body. As such it has the same cache
metadata update properties as 304 responses or merge of 204 responses.

Regards
Henrik

---

From: Henrik Nordström <[email-masked]>
Date: Thu, 16 Feb 2012 08:22:18 +0100

> 1. Since it specifies required cache behaviour, it really should be in p6

Yes.

> 2. The second MAY seems to conflict with the MUST

Not really but should perhaps read "cached", not "cache".

It's a mutually exclusive condition. Remember that MUST have priority
over MAY, and with the two even in the same sentence there isn't much
room for confusion.

If the cached entry identity matches the HEAD response then it may be
updated with information from HEAD just as in the case of 304 responses
or 204 responses.

If the cached entry identity do not match the HEAD response then the
cached entry is stale even if it's cached expiry information says
otherwise.

> 3. Caches can store multiple representations for a resource, so there is no "current representation."

Not really a problem.

If there is no Vary then URI == Resource.

On resources using Vary then representations of URIs should have
identification means making them unique

a) ETag
b) Content-Location

and on Vary not using * then there is a clear mapping of
request->representation allowing HEAD responses to clearly indicate
earlier responses that match this request as stale.

> Part of the problem here really is that it's not "updating" any
> response, but it is potentially invalidating an old one.

What?

HEAD responses that match the cached representation may update the
cached representation with new Date etc. It's a form of cache validation
if you like.

> To resolve this, we could construct a requirement that refers to p6
> 2.7 ("Caching Negotiated Responses") to identify the correct response
> to compare to and (potentially) invalidate. 

It's simply the last known response that matches the request.

This response may be composed by aggregating many earlier responses

304
HEAD response
merged 204 responses
partial 200 response
200 response

> However, I wonder if a) this is widely implemented, and b) the

a) Probably not.

b) Probably worthwhile explaining the above response merge model of
caches.

> I.e., we could alternatively just remove everything after the first
> sentence (i.e., treat the second MAY as primary, and therefore make
> the whole thing redundant).

Some common guidance on how/when cache entries are
updated/merged/invalidated may help. The same properties & conditions
applies in all cases. Both in intent (keeping cache up to date avoiding
unneeded roundtrips) and issues (avoiding bad updates, servers not
providing correct data in many cases)

Regards
Henrik