Subject: #241: clarify eval order/interaction of conditional headers

From: Mark Nottingham <[email-masked]>
Date: Tue, 3 Jul 2012 17:37:20 +1000

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

Roy documented the evaluation order for conditional that Apache uses (which, he pointed out, is the only logical way to do it, once you look at it):

<http://trac.tools.ietf.org/wg/httpbis/trac/ticket/241#comment:4>

> Here is the order that Apache httpd uses. When I wrote it, I realized that there is only one logical order for preconditions because ETag is presumed to be more accurate than LM. Likewise, the exact match fields (If-Match and If-Unmodified-Since) have priority over the weaker conditions in the unlikely event that they are ever used together in the same request.
> 
> Check for conditional requests — note that we only want to do this if we are successful so far and we are not processing a subrequest or an ErrorDocument?.
> 
> The order of the checks is important, since ETag checks are supposed to be more accurate than checks relative to the modification time. However, not all documents are guaranteed to have ETags, and some might have Last-Modified values w/o ETags, so this gets a little complicated.
> 
> If an If-Match request-header field was given AND the field value is not "*" (meaning match anything) AND if our strong ETag does not match any entity tag in that field, respond with a status of 412 (Precondition Failed).
> 
> Else if a valid If-Unmodified-Since request-header field was given AND the requested resource has been modified since the time specified in this field, then the server MUST respond with a status of 412 (Precondition Failed).
> 
> If an If-None-Match request-header field was given AND the field value is "*" (meaning match anything) OR our ETag matches any of the entity tags in that field, fail.
> 
> If the request method was GET or HEAD, failure means the server SHOULD respond with a 304 (Not Modified) response. For all other request methods, failure means the server MUST respond with a status of 412 (Precondition Failed).
> 
> GET or HEAD allow weak etag comparison, all other methods require strong comparison. We can only use weak if it's not a range request.
> 
> If a valid If-Modified-Since request-header field was given AND it is a GET or HEAD request AND the requested resource has not been modified since the time specified in this field, then the server MUST respond with a status of 304 (Not Modified). A date later than the server's current request time is invalid.

This is somewhat implementation-specific, but I think the next step is for the editors to turn this into suitable specification text. If you have feedback on the *high-level* approach taken here, now would be good.

Regards,

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

---

From: Zhong Yu <[email-masked]>
Date: Wed, 4 Jul 2012 11:30:00 -0500

I think there's a problem.

If both If-Non-Match and If-Mod-Since are given, and they are
evaluated to TRUE and FALSE respectively, the algorithm yields 304 Not
Modified.  The "Not Modified" response is totally wrong, since the
ETag has been updated.

For example, if the current representation has  ETag=v1.0,
Last-Mod=7/1, and the request has
    If-Non-Match: v1.1
    If-Mod-Since: 7/4
the server should respond 200 with the current representation, not a 304.

The solution seems to be that, if both headers are given, only
If-Non-Match should be looked at; the If-Mod-Since condition must be
ignored.

Zhong Yu

---

From: Mark Nottingham <[email-masked]>
Date: Thu, 5 Jul 2012 09:37:42 +1000

Indeed, and testing my local install of Apache, it seems that it makes this exception too.

Thanks,

---

From: Julian Reschke <[email-masked]>
Date: Thu, 12 Jul 2012 09:08:21 +0200

On 2012-07-03 09:37, Mark Nottingham wrote:
> ...

I'd like to avoid to include pseudo-code like that *unless* it's really 
needed.

Do we really need to define the evaluation order? In what real-world 
situations well there be more than one condition?

Wouldn't it be simpler to:

1) Formally define the condition expressed by each header field,

and

2) State that all conditions must be met, otherwise a 412 will be 
returned (with the 304 variant special-cased).

Best regards, Julian

---

From: "Roy T. Fielding" <[email-masked]>
Date: Thu, 12 Jul 2012 11:38:26 -0700

On Jul 12, 2012, at 12:08 AM, Julian Reschke wrote:

> I'd like to avoid to include pseudo-code like that *unless* it's really needed.

So would I ... the text provided is just the comments from the code.
Once the result is agreed, we can work on text.

> Do we really need to define the evaluation order? In what real-world situations well there be more than one condition?
> 
> 2) State that all conditions must be met, otherwise a 412 will be returned (with the 304 variant special-cased).

No, because it isn't true in practice (nor desired).  We actually
do want an etag to override last-modified even when IMS is false.

....Roy

---

From: Julian Reschke <[email-masked]>
Date: Thu, 12 Jul 2012 21:44:47 +0200

> do want an etag to override last-modified even when IMS is false.

So that use case is a request with both "If-None-Match" and 
"If-Modified-Since", where the Etag condition is true, but the timestamp 
condition is not?

Does this happen frequently in practice? What's the reason for sending 
both header fields when the ETag is available? (Trying to understand...)

Best regards, Julian

---

From: "Eric J. Bowman" <[email-masked]>
Date: Thu, 12 Jul 2012 17:07:28 -0600

Julian Reschke wrote:
>
> What's the reason for sending both header fields when the ETag is
> available? (Trying to understand...)
> 

HTTP 1.0 intermediary back-compat, so I've heard.

-Eric

---

From: "Roy T. Fielding" <[email-masked]>
Date: Thu, 12 Jul 2012 22:42:08 -0700

> HTTP 1.0 intermediary back-compat, so I've heard.

Yep, and for 1.1 intermediaries that do not implement If-None-Match
for reasons unknown.

....Roy