RE: No validator in 200 response for conditional update

Thanks for your replies!

In general, since the spec says that server "MUST NOT" send an ETag in some case so in order to comply with the spec we must implement that logic and it does not matter if it is a corner case or if it may happen only once in our API. In reality it is actually not an edge case and happens quite often (up to single digit % of all requests in high volume concurrent scenarios).

That's why I am trying to understand the reason because that clause calls for a lot of development.

Why "a lot" of development?
Because the clause "... unless it can verify that the request is a duplicate of an immediately prior change made by the same user agent ..." requires us to persistently track previous requests from all clients which is a huge infra requirement for stateless API server farms (which is a typical design for servers with high performance requirements).

Actually, scenario of that 2xx clause (as I read it) is a bit more complicated - it applies in the case when 2 agents (A1 and A2) are talking to the sever and trying to apply semantically same changes or same agent asks for the same change in non-consecutive requests. Here is my understanding:
1) "state change is being requested and the final state is already reflected in the current state" ==> means that requests may not be identical, as long as they ask for the same end-result state.
2) "server MUST NOT send a validator header field in the response unless it can verify that the request is a duplicate of an immediately prior change made by the same user agent " ==> means that:
a) server MUST NOT send ETag to A2 if state change was done by A1, but similar change is requested by A2
b) server MUST NOT send ETag to A1 if state change was done by A1 but there was some other request (even GET without any side-effects) between that original change request and a new, semantically-identical change request.

So expanding on Yishuai's example to include all cases it would be something like:

(step 1) A1 --> S : PUT "a" (unconditional)
(step 2) S --> A1 : 204 No Content, ETag: "a"
(step 3) A1 --> S : PUT "a", If-Match: "b" (not satisfied)
(step 4) S --> A1 : 204 No Content, ETag: "a" (same change-originating agent, same end-result requested in the immediate prior request)
(step 5) A2 --> S : PUT "a", If-Match: "b" (not satisfied)
(step 6) S --> A1 : 204 No Content (No ETag) (not a change-originating agent, same end-result requested)
(step 7) A1 --> S : GET ... (unconditional, no side-effects)
(step 8) S-> A1 (doesn't matter what is replied here)
(step 9) A1 --> S : PUT "a", If-Match: "b" (not satisfied)
(step 10) S --> A1 : 204 No Content (No ETag) (same change-originating agent, same end-result requested, but not in the immediate prior request)
(step 11) A3 --> S : PUT "zzz", If-Match: "b" (not satisfied)
(step 12) S --> A1 : 412 No Content (No ETag) (any agent, different end-result requested)

My question is about (step 6) and (step 10) where server MUST NOT send a ETag value back. 
Above is quite complicated logic required without explanation and it is not clear of how it is better/safer than simple and stateless:
(step 1) A1 --> S : PUT "a" (unconditional)
(step 2) S --> A1 : 204 No Content, ETag: "a"
(step 3) A1 --> S : PUT "a", If-Match: "b" (not satisfied)
(step 4) S --> A1 : 204 No Content, ETag: "a" (any agent, same end-result requested)
 (step 11) A3 --> S : PUT "zzz", If-Match: "b" (not satisfied)
(step 12) S --> A1 : 412 No Content (No ETag) (any agent, different end-result requested)

Thanks,
Vladimir

-----Original Message-----
From: Julian Reschke <julian.reschke@gmx.de> 
Sent: Monday, October 29, 2018 10:06 AM
To: Yishuai Li <yishuai@cis.upenn.edu>; Vladimir Lashchev <vladimir.lashchev@oracle.com>
Cc: ietf-http-wg@w3.org
Subject: Re: No validator in 200 response for conditional update

On 2018-10-27 08:04, Yishuai Li wrote:
> I am also confused by this clause. Consider the following scenario 
> (for simplicity, the entity-tag is identical to entity, and the all 
> requests have the same target):
> 
> (1) A --> S : PUT "a" (unconditional)
> (2) S --> A : 204 No Content, ETag: "a"
> (3) A --> S : PUT "a", If-Match: "b" (not satisfied)
> (4) S --> A : 204 No Content
> (5) A --> S : PUT "a", If-Match: "b" (not satisfied)
> (6) S --> A : 204 No Content, ETag "a"
> 
> Did I understand the specification correctly that: S MUST NOT send a 
> validator in (4), but MAY do so in (6), because (5) is a duplicate of 
> (3), but (3) is not a duplicate of (1)?
> 
> Thanks,
> Yishuai Li
> ...

Ok, now I understand the question. Ignore my previous reply.

So that's an edge case of an edge case, right?

The spec says:

>    An origin server MUST NOT perform the requested method if a received
>    If-Match condition evaluates to false; instead, the origin server
>    MUST respond with either a) the 412 (Precondition Failed) status code
>    or b) one of the 2xx (Successful) status codes if the origin server
>    has verified that a state change is being requested and the final
>    state is already reflected in the current state of the target
>    resource (i.e., the change requested by the user agent has already
>    succeeded, but the user agent might not be aware of it, perhaps
>    because the prior response was lost or a compatible change was made
>    by some other user agent).  In the latter case, the origin server
>    MUST NOT send a validator header field in the response unless it can
>    verify that the request is a duplicate of an immediately prior change
>    made by the same user agent.

Note the "immediately prior change" - so no (4) did not result in a change, so the rule does not apply and no etag should be sent.

Best regards, Julian

Received on Tuesday, 6 November 2018 22:35:59 UTC