Subject: #372: refactor conditional header field descriptions

From: Julian Reschke <[email-masked]>
Date: Tue, 10 Jul 2012 22:17:52 +0200

(see http://trac.tools.ietf.org/wg/httpbis/trac/ticket/372)

While looking at If-Match and If-None-Match I realized that there's a 
lot of prose we repeat, and then sometimes do not get it right.

I'd like to refactor these so that the condition is only defined once.

Proposal for If-Match:

diff -r19.43 draft-ietf-httpbis-p4-conditional-latest.unpg.txt
630,640c630,641
<  If any of the entity-tags listed in the If-Match field value match
<  (as per Section 2.3.2) the entity-tag of the selected representation
<  for the target resource, or if "*" is given and any current
<  representation exists for the target resource, then the server MAY
<  perform the request method as if the If-Match header field was not
<  present.
<
<  Origin servers MUST NOT perform the requested method if none of the
<  entity-tags match, or if "*" is given and no current representation
<  exists; instead they MUST respond with the 412 (Precondition Failed)
<  status code.
---
 >  The If-Match condition is met if and only if any of the entity-tags
 >  listed in the If-Match field value match (as per Section 2.3.2) the
 >  entity-tag of the selected representation for the target resource, or
 >  if "*" is given and any current representation exists for the target
 >  resource.
 >
 >  If the condition is met, the server MAY perform the request method as
 >  if the If-Match header field was not present.
 >
 >  Origin servers MUST NOT perform the requested method if the condition
 >  is not met; instead they MUST respond with the 412 (Precondition
 >  Failed) status code.
643,644c644
<  MUST NOT perform the requested method if none of the entity-tags
<  match, or if "*" is given and no current representation exists;
---
 >  MUST NOT perform the requested method if the condition is not met;

and for If-None-Match:

<  If any of the entity-tags listed in the If-None-Match field-value
<  match (as per Section 2.3.2) the entity-tag of the selected
<  representation, or if "*" is given and any current representation
<  exists for that resource, then the server MUST NOT perform the
<  requested method.  Instead, if the request method was GET or HEAD,
<  the server SHOULD respond with a 304 (Not Modified) status code,
<  including the cache-related header fields (particularly ETag) of the
<  selected representation that has a matching entity-tag.  For all
<  other request methods, the server MUST respond with a 412
<  (Precondition Failed) status code.
<
<  If none of the entity-tags match, then the server MAY perform the
<  requested method as if the If-None-Match header field did not exist,
<  but MUST also ignore any If-Modified-Since header field(s) in the
<  request.  That is, if no entity-tags match, then the server MUST NOT
<  return a 304 (Not Modified) response.
---
 >  The If-None-Match condition is met if and only if any of the entity-
 >  tags listed in the If-None-Match field-value match (as per
 >  Section 2.3.2) the entity-tag of the selected representation, or if
 >  "*" is given and any current representation exists for that resource.
 >
 >  If the condition is met, the server MUST NOT perform the requested
 >  method.  Instead, if the request method was GET or HEAD, the server
 >  SHOULD respond with a 304 (Not Modified) status code, including the
 >  cache-related header fields (particularly ETag) of the selected
 >  representation that has a matching entity-tag.  For all other request
 >  methods, the server MUST respond with a 412 (Precondition Failed)
 >  status code.
 >
 >  If the condition is not met, the server MAY perform the requested
 >  method as if the If-None-Match header field did not exist, but MUST
 >  also ignore any If-Modified-Since header field(s) in the request.
 >  That is, if no entity-tags match, then the server MUST NOT return a
 >  304 (Not Modified) response.

(See 
<http://trac.tools.ietf.org/wg/httpbis/trac/attachment/ticket/372/372.diff>)

Feedback appreciated,

Julian

---

From: Mark Nottingham <[email-masked]>
Date: Thu, 12 Jul 2012 14:14:56 +1000

+1

On 11/07/2012, at 6:17 AM, Julian Reschke wrote:

> While looking at If-Match and If-None-Match I realized that there's a lot of prose we repeat, and then sometimes do not get it right.
> 
> (See <http://trac.tools.ietf.org/wg/httpbis/trac/attachment/ticket/372/372.diff>)
> 
> Feedback appreciated,
> 
> Julian
> 

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

---

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

Thanks; in the meantime I came to the conclusion that the definition of 
"condition met" for If-None-Match needs to be reversed. (The text was 
consistent, but in a confusing way). I also made the two definitions 
more consistent.

Proposed patch: 
<http://trac.tools.ietf.org/wg/httpbis/trac/attachment/ticket/372/372.2.diff>

The definition for "condition met" on If-Match would be:

    The If-Match condition is met if and only if any of the entity-tags
    listed in the If-Match field value match the entity-tag of the
    selected representation for the target resource (as per
    Section 2.3.2), or if "*" is given and any current representation
    exists for the target resource.

For If-None-Match:

    The If-None-Match condition is met if and only if none of the entity-
    tags listed in the If-None-Match field value match the entity-tag of
    the selected representation for the target resource (as per
    Section 2.3.2), or if "*" is given and no current representation
    exists for that resource.

Complete text for both header fields:

3.1.  If-Match

    The "If-Match" header field can be used to make a request method
    conditional on the current existence or value of an entity-tag for
    one or more representations of the target resource.

    If-Match is generally useful for resource update requests, such as
    PUT requests, as a means for protecting against accidental overwrites
    when multiple clients are acting in parallel on the same resource
    (i.e., the "lost update" problem).  An If-Match field-value of "*"
    places the precondition on the existence of any current
    representation for the target resource.

      If-Match = "*" / 1#entity-tag

    The If-Match condition is met if and only if any of the entity-tags
    listed in the If-Match field value match the entity-tag of the
    selected representation for the target resource (as per
    Section 2.3.2), or if "*" is given and any current representation
    exists for the target resource.

    Proxy servers using a cached response as the selected representation
    MUST NOT perform the requested method if the condition is not met;
    instead, they MUST forward the request towards the origin server.

    If the request would, without the If-Match header field, result in
    anything other than a 2xx (Successful) or 412 (Precondition Failed)
    status code, then the If-Match header field MUST be ignored.

    Examples:

      If-Match: "xyzzy"
      If-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
      If-Match: *

    The result of a request having both an If-Match header field and
    either an If-None-Match or an If-Modified-Since header field is
    undefined by this specification.

3.2.  If-None-Match

    The "If-None-Match" header field can be used to make a request method
    conditional on not matching any of the current entity-tag values for
    representations of the target resource.

    If-None-Match is primarily used in conditional GET requests to enable
    efficient updates of cached information with a minimum amount of
    transaction overhead.  A client that has one or more representations
    previously obtained from the target resource can send If-None-Match
    with a list of the associated entity-tags in the hope of receiving a
    304 (Not Modified) response if at least one of those representations
    matches the selected representation.

    If-None-Match can also be used with a value of "*" to prevent an
    unsafe request method (e.g., PUT) from inadvertently modifying an
    existing representation of the target resource when the client
    believes that the resource does not have a current representation.
    This is a variation on the "lost update" problem that might arise if
    more than one client attempts to create an initial representation for
    the target resource.

      If-None-Match = "*" / 1#entity-tag

    The If-None-Match condition is met if and only if none of the entity-
    tags listed in the If-None-Match field value match the entity-tag of
    the selected representation for the target resource (as per
    Section 2.3.2), or if "*" is given and no current representation
    exists for that resource.

    If the condition is not met, the server MUST NOT perform the
    requested method.  Instead, if the request method was GET or HEAD,
    the server SHOULD respond with a 304 (Not Modified) status code,
    including the cache-related header fields (particularly ETag) of the
    selected representation that has a matching entity-tag.  For all
    other request methods, the server MUST respond with a 412
    (Precondition Failed) status code.

    If the condition is met, the server MAY perform the requested method
    as if the If-None-Match header field did not exist, but MUST also
    ignore any If-Modified-Since header field(s) in the request.  That
    is, if no entity-tags match, then the server MUST NOT return a 304
    (Not Modified) response.

    If the request would, without the If-None-Match header field, result
    in anything other than a 2xx (Successful) or 304 (Not Modified)
    status code, then the If-None-Match header field MUST be ignored.
    (See Section 2.4 for a discussion of server behavior when both If-
    Modified-Since and If-None-Match appear in the same request.)

    Examples:

      If-None-Match: "xyzzy"
      If-None-Match: W/"xyzzy"
      If-None-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
      If-None-Match: W/"xyzzy", W/"r2d2xxxx", W/"c3piozzzz"
      If-None-Match: *

    The result of a request having both an If-None-Match header field and
    either an If-Match or an If-Unmodified-Since header field is
    undefined by this specification.

Feedback appreciated, Julian

---

From: Willy Tarreau <[email-masked]>
Date: Thu, 12 Jul 2012 09:11:56 +0200

Hi Julian,

> <http://trac.tools.ietf.org/wg/httpbis/trac/attachment/ticket/372/372.2.diff>
(...)
> Feedback appreciated, Julian

The wording and use cases are very clear to me that way and I think this is
exactly what is needed ! I'd say "please don't change a word".

Cheers,
Willy

---

From: Julian Reschke <[email-masked]>
Date: Thu, 12 Jul 2012 12:16:24 +0200

On 2012-07-12 09:11, Willy Tarreau wrote:
> ...

Your wish is my command: 
<http://trac.tools.ietf.org/wg/httpbis/trac/changeset/1761>

Best regards, Julian