Uploaded image for project: 'OASIS Content Management Interoperability Services (CMIS) TC'
  1. OASIS Content Management Interoperability Services (CMIS) TC
  2. CMIS-656

Clarify how ETags and cmis:changeToken interact

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Major
    • Resolution: Applied
    • Affects Version/s: None
    • Fix Version/s: V1.0 Errata
    • Component/s: REST/AtomPub Binding
    • Labels:
      None
    • Proposal:
      Hide

      2. On updates, perform the following checks (HTTP & CMIS levels)
      2.1 If If-Match header is sent by client, ETag value is pulled from HTTP header If-Match per RFC2616. The supplied ETag is compared against the ETag on the server. If the match fails, then status code 412 is used.
      2.2 If cmis:changeToken property is supplied by the client, compare the supplied and the cmis:changeToken on the server. If the comparison fails, then return status code 409 per CMIS.
      2.3 If ETag and cmis:changeToken are both specified, the HTTP If-Match check should be performed first.

      Show
      2. On updates, perform the following checks (HTTP & CMIS levels) 2.1 If If-Match header is sent by client, ETag value is pulled from HTTP header If-Match per RFC2616. The supplied ETag is compared against the ETag on the server. If the match fails, then status code 412 is used. 2.2 If cmis:changeToken property is supplied by the client, compare the supplied and the cmis:changeToken on the server. If the comparison fails, then return status code 409 per CMIS. 2.3 If ETag and cmis:changeToken are both specified, the HTTP If-Match check should be performed first.

      Description

      RFC5023 uses If-Match in the example in 9.5.1. As such, the server MUST return 412 if the ETag does not match. RFC5023 does not have normative language around status code 412 and is only used in the example.

      As I read the relevant RFCs, I get the following:

      2. On updates, perform the following checks (HTTP & CMIS levels)
      2.1 If If-Match header is sent by client, ETag value is pulled from HTTP header If-Match per RFC2616. The supplied ETag is compared against the ETag on the server. If the match fails, then status code 412 is used.
      2.2 If cmis:changeToken property is supplied by the client, compare the supplied and the cmis:changeToken on the server. If the comparison fails, then return status code 409 per CMIS.
      2.3 If ETag and cmis:changeToken are both specified, the HTTP If-Match check should be performed first.

      This provides normal HTTP behavior if ETag/If-Match headers are used (code 412). If cmis:changeToken is used, the follow the advice in the HTTP spec and use 409 Conflict.

      The difference in status codes comes down to HTTP modelling the optimistic versioning as a client constraint. E.g., client states don't perform the PUT if the resource is different from ETag XXXX. Technically if the If-Match header was not specified by the client, the PUT would go through if the cmis:changeToken check was not there. The CMIS model is a server constraint and thus the 409 status code.

      Backup material:

      HTTP RFC 2616 states:

      409 Conflict
      The request could not be completed due to a conflict with the current state of the resource. This code is only allowed in situations where it is expected that the user might be able to resolve the conflict and resubmit the request. The response body SHOULD include enough
      information for the user to recognize the source of the conflict. Ideally, the response entity would include enough information for the user or user agent to fix the problem; however, that might not be possible and is not required.
      Conflicts are most likely to occur in response to a PUT request. For example, if versioning were being used and the entity being PUT included changes to a resource which conflict with those made by an earlier (third-party) request, the server might use the 409 response to indicate that it can't complete the request. In this case, the response entity would likely contain a list of the differences between the two versions in a format defined by the response Content-Type.

      412 Precondition Failed
      The precondition given in one or more of the request-header fields evaluated to false when it was tested on the server. This response code allows the client to place preconditions on the current resource metainformation (header field data) and thus prevent the requested method from being applied to a resource other than the one intended.
      14.24 If-Match
      The If-Match request-header field is used with a method to make it conditional. A client that has one or more entities previously obtained from the resource can verify that one of those entities is current by including a list of their associated entity tags in the If-Match header field. Entity tags are defined in section 3.11. The purpose of this feature is to allow efficient updates of cached information with a minimum amount of transaction overhead. It is also used, on updating requests, to prevent inadvertent modification of the wrong version of a resource. As a special case, the value "*" matches any current entity of the resource.
      If-Match = "If-Match" ":" ( "*" | 1#entity-tag )

      If any of the entity tags match the entity tag of the entity that would have been returned in the response to a similar GET request (without the If-Match header) on that resource, or if "*" is given
      and any current entity exists for that resource, then the server MAY perform the requested method as if the If-Match header field did not exist.
      A server MUST use the strong comparison function (see section 13.3.3) to compare the entity tags in If-Match.
      If none of the entity tags match, or if "*" is given and no current entity exists, the server MUST NOT perform the requested method, and MUST return a 412 (Precondition Failed) response. This behavior is most useful when the client wants to prevent an updating method, such as PUT, from modifying a resource that has changed since the client last retrieved it.
      If the request would, without the If-Match header field, result in anything other than a 2xx or 412 status, then the If-Match header MUST be ignored.
      The meaning of "If-Match: *" is that the method SHOULD be performed if the representation selected by the origin server (or by a cache, possibly using the Vary mechanism, see section 14.44) exists, and MUST NOT be performed if the representation does not exist.
      A request intended to update a resource (e.g., a PUT) MAY include an If-Match header field to signal that the request method MUST NOT be applied if the entity corresponding to the If-Match value (a single entity tag) is no longer a representation of that resource. This allows the user to indicate that they do not wish the request to be successful if the resource has been changed without their knowledge. 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 fields is undefined by this specification.

        Attachments

          Activity

            People

            • Assignee:
              fmueller Florian Müller (Inactive)
              Reporter:
              albertcbrown Al Brown (Inactive)
            • Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: