Table of contents
- List Evaluation
- Matching State Tokens and ETags
- If Header and Non-DAV-Aware Proxies
- Example - No-tag Production
- Example - Using "Not" with No-tag Production
- Example - Causing a Condition to Always Evaluate to True
- Example - Tagged List If Header in COPY
- Example - Matching Lock Tokens with Collection Locks
- Example - Matching ETags on Unmapped URLs
The If request header is intended to have similar functionality to the If-Match header defined in Section 14.24 of [RFC2616]. However, the If header handles any state token as well as ETags. A typical example of a state token is a lock token, and lock tokens are the only state tokens defined in this specification.
The If header has two distinct purposes:
- The first purpose is to make a request conditional by supplying a series of state lists with conditions that match tokens and ETags to a specific resource. If this header is evaluated and all state lists fail, then the request MUST fail with a 412 (Precondition Failed) status. On the other hand, the request can succeed only if one of the described state lists succeeds. The success criteria for state lists and matching functions are defined in Sections 10.4.3 and 10.4.4.
- Additionally, the mere fact that a state token appears in an If header means that it has been "submitted" with the request. In general, this is used to indicate that the client has knowledge of that state token. The semantics for submitting a state token depend on its type (for lock tokens, please refer to Section 6).
Note that these two purposes need to be treated distinctly: a state token counts as being submitted independently of whether the server actually has evaluated the state list it appears in, and also independently of whether or not the condition it expressed was found to be true.
If = "If" ":" ( 1*No-tag-list | 1*Tagged-list ) No-tag-list = List Tagged-list = Resource-Tag 1*List List = "(" 1*Condition ")" Condition = ["Not"] (State-token | "[" entity-tag "]") ; entity-tag: see Section 3.11 of [RFC2616] ; No LWS allowed between "[", entity-tag and "]" State-token = Coded-URL Resource-Tag = "<" Simple-ref ">" ; Simple-ref: see Section 8.3 ; No LWS allowed in Resource-Tag
The syntax distinguishes between untagged lists ("No-tag-list") and tagged lists ("Tagged-list"). Untagged lists apply to the resource identified by the Request-URI, while tagged lists apply to the resource identified by the preceding Resource-Tag.
A Resource-Tag applies to all subsequent Lists, up to the next Resource-Tag.
Note that the two list types cannot be mixed within an If header. This is not a functional restriction because the No-tag-list syntax is just a shorthand notation for a Tagged-list production with a Resource-Tag referring to the Request-URI.
Each List consists of one or more Conditions. Each Condition is defined in terms of an entity-tag or state-token, potentially negated by the prefix "Not".
Note that the If header syntax does not allow multiple instances of If headers in a single request. However, the HTTP header syntax allows extending single header values across multiple lines, by inserting a line break followed by whitespace (see [RFC2616], Section 4.2).
A Condition that consists of a single entity-tag or state-token evaluates to true if the resource matches the described state (where the individual matching functions are defined below in Section 10.4.4). Prefixing it with "Not" reverses the result of the evaluation (thus, the "Not" applies only to the subsequent entity-tag or state-token).
Each List production describes a series of conditions. The whole list evaluates to true if and only if each condition evaluates to true (that is, the list represents a logical conjunction of Conditions).
Each No-tag-list and Tagged-list production may contain one or more Lists. They evaluate to true if and only if any of the contained lists evaluates to true (that is, if there's more than one List, that List sequence represents a logical disjunction of the Lists).
Finally, the whole If header evaluates to true if and only if at least one of the No-tag-list or Tagged-list productions evaluates to true. If the header evaluates to false, the server MUST reject the request with a 412 (Precondition Failed) status. Otherwise, execution of the request can proceed as if the header wasn't present.
Matching State Tokens and ETags
When performing If header processing, the definition of a matching state token or entity tag is as follows:
Identifying a resource: The resource is identified by the URI along with the token, in tagged list production, or by the Request-URI in untagged list production.
Matching entity tag: Where the entity tag matches an entity tag associated with the identified resource. Servers MUST use either the weak or the strong comparison function defined in Section 13.3.3 of [RFC2616].
Matching state token: Where there is an exact match between the state token in the If header and any state token on the identified resource. A lock state token is considered to match if the resource is anywhere in the scope of the lock.
Handling unmapped URLs: For both ETags and state tokens, treat as if the URL identified a resource that exists but does not have the specified state.
If Header and Non-DAV-Aware Proxies
Non-DAV-aware proxies will not honor the If header, since they will not understand the If header, and HTTP requires non-understood headers to be ignored. When communicating with HTTP/1.1 proxies, the client MUST use the "Cache-Control: no-cache" request header so as to prevent the proxy from improperly trying to service the request from its cache. When dealing with HTTP/1.0 proxies, the "Pragma: no-cache" request header MUST be used for the same reason.
Because in general clients may not be able to reliably detect non-DAV-aware intermediates, they are advised to always prevent caching using the request directives mentioned above.
Example - No-tag Production
If: (<urn:uuid:181d4fae-7d8c-11d0-a765-00a0c91e6bf2> ["I am an ETag"]) (["I am another ETag"])
The previous header would require that the resource identified in the Request-URI be locked with the specified lock token and be in the state identified by the "I am an ETag" ETag or in the state identified by the second ETag "I am another ETag".
To put the matter more plainly one can think of the previous If header as expressing the condition below:
( is-locked-with(urn:uuid:181d4fae-7d8c-11d0-a765-00a0c91e6bf2) AND matches-etag("I am an ETag") ) OR ( matches-etag("I am another ETag") )
Example - Using "Not" with No-tag Production
If: (Not <urn:uuid:181d4fae-7d8c-11d0-a765-00a0c91e6bf2> <urn:uuid:58f202ac-22cf-11d1-b12d-002035b29092>)
This If header requires that the resource must not be locked with a lock having the lock token urn:uuid:181d4fae-7d8c-11d0-a765-00a0c91e6bf2 and must be locked by a lock with the lock token urn:uuid:58f202ac-22cf-11d1-b12d-002035b29092.
Example - Causing a Condition to Always Evaluate to True
There may be cases where a client wishes to submit state tokens, but doesn't want the request to fail just because the state token isn't current anymore. One simple way to do this is to include a Condition that is known to always evaluate to true, such as in:
If: (<urn:uuid:181d4fae-7d8c-11d0-a765-00a0c91e6bf2>) (Not <DAV:no-lock>)
"DAV:no-lock" is known to never represent a current lock token. Lock tokens are assigned by the server, following the uniqueness requirements described in Section 6.5, therefore cannot use the "DAV:" scheme. Thus, by applying "Not" to a state token that is known not to be current, the Condition always evaluates to true. Consequently, the whole If header will always evaluate to true, and the lock token urn:uuid:181d4fae-7d8c-11d0-a765-00a0c91e6bf2 will be submitted in any case.
Example - Tagged List If Header in COPY
COPY /resource1 HTTP/1.1 Host: www.example.com Destination: /resource2 If: </resource1> (<urn:uuid:181d4fae-7d8c-11d0-a765-00a0c91e6bf2> [W/"A weak ETag"]) (["strong ETag"])
In this example, http://www.example.com/resource1 is being copied to http://www.example.com/resource2. When the method is first applied to http://www.example.com/resource1, resource1 must be in the state specified by "(<urn:uuid:181d4fae-7d8c-11d0-a765-00a0c91e6bf2> [W/"A weak ETag"]) (["strong ETag"])". That is, either it must be locked with a lock token of "urn:uuid:181d4fae-7d8c-11d0-a765-00a0c91e6bf2" and have a weak entity tag W/"A weak ETag" or it must have a strong entity tag "strong ETag".
Example - Matching Lock Tokens with Collection Locks
DELETE /specs/rfc2518.txt HTTP/1.1 Host: www.example.com If: <http://www.example.com/specs/> (<urn:uuid:181d4fae-7d8c-11d0-a765-00a0c91e6bf2>)
For this example, the lock token must be compared to the identified resource, which is the 'specs' collection identified by the URL in the tagged list production. If the 'specs' collection is not locked by a lock with the specified lock token, the request MUST fail. Otherwise, this request could succeed, because the If header evaluates to true, and because the lock token for the lock affecting the affected resource has been submitted.
Example - Matching ETags on Unmapped URLs
Consider a collection "/specs" that does not contain the member "/specs/rfc2518.doc". In this case, the If header
If: </specs/rfc2518.doc> (["4217"])
will evaluate to false (the URI isn't mapped, thus the resource identified by the URI doesn't have an entity matching the ETag "4217").
On the other hand, an If header of
If: </specs/rfc2518.doc> (Not ["4217"])
will consequently evaluate to true.
Note that, as defined above in Section 10.4.4, the same considerations apply to matching state tokens.