Loading ...
Sorry, an error occurred while loading the content.

PUT or POST, idempotent for the application

Expand Messages
  • Bruno Harbulot
    Hello, Apologies if I revive last week s thread about POST being idempotent or not, but it got me confused on the choice between using POST or PUT in the
    Message 1 of 4 , Jul 5, 2007
    • 0 Attachment
      Hello,


      Apologies if I revive last week's thread about POST being idempotent or
      not, but it got me confused on the choice between using POST or PUT in
      the system on which I'm working, and idempotent messages matter in this
      case.


      We've designed a system (which I believe complies with the REST
      principles) that relies on a client interacting with a resource to
      create other resources.


      To summarise how this system works, a client can ask the Factory
      resource to create Item resources. The process of creating an Item
      resource must follow two constraints:
      - at the end of the process, the client must have created one Item
      resource and must know its URI;
      - at the end of the process, the Factory resource must know that the
      client knows the new Item resource URI.

      Initially, we assume the client has been configured to know the URI of
      the Factory: http://example.org/Factory.

      The protocol we use is as follows (the numbers in the URIs are just
      examples):

      (phase 1: tentative)
      C: HTTP PUT to http://example.org/Factory containing <newItemReq />
      S: HTTP 201 with Location: http://example.org/Item/1

      (phase 2: activation)
      C: HTTP PUT to http://example.org/Item/1 containing <resActivator />
      S: HTTP 200 OK.


      An HTTP GET on http://example.org/Factory returns a list of all the
      Items that have been created and 'activated' (i.e. of which the Factory
      knows that the client knows their address).
      If the Factory never receives the second PUT, the Item resource is not
      the list document. (Optionally, if the client interacts later with the
      Item resource, this may activate this resource anyway). Item resources
      that are not activated may be discarded at any time by the Factory (in
      which case the client would have to re-start the entire process.)

      Here is an example of what could go wrong and how this would be handled:

      (phase 1: tentative)
      C: HTTP PUT to http://example.org/Factory containing <newItemReq />
      S: HTTP 201 with Location: http://example.org/Item/1
      - the connection is lost and the new URI never reaches the client.

      (phase 1: another attempt)
      C: HTTP PUT to http://example.org/Factory containing <newItemReq />
      S: HTTP 201 with Location: http://example.org/Item/2

      (phase 2: activation)
      C: HTTP PUT to http://example.org/Item/2 containing <resActivator />
      S: HTTP 200 OK.
      - the client knows the URI of the Item it has successfully created,
      and the factory knows that the client knows.



      The 'activation' PUT is idempotent because sending it N+1 times has the
      same effect as sending it just once.

      I also think the first 'tentative' PUT is idempotent, although it is
      more subtle. Effectively, whatever the URI returned in the tentative
      phase is does not matter, either to the client or to the factory. When
      taking into account the two phases, sending N+1 'tentative' PUT + an
      'activation' has the same result as sending only one tentative PUT
      followed by an activation: only one Item resource is activated and both
      the client and the server know about its URI.


      When reading Section 9.5 and 9.6 of RFC 2616, my use of PUT here is not
      appropriate, and it should probably be POST, in both cases, for two
      different reasons:
      - the 'tentative' PUT clearly does not comply with "the URI in a PUT
      request identifies the entity enclosed with the request" (in Section 9.6);
      - the 'activation' PUT might rather be considered as an "annotation
      of existing resources" (in Section 9.5).



      I'm tempted to change these two PUTs into POSTs. However, I quite like
      the fact that PUT is intended to be idempotent. I believe the fact that
      a request is guaranteed to be idempotent is more important than "the URI
      in a PUT request identifies the entity enclosed with the request" when
      designing distributed systems.
      Obviously, the use of POST in this system may be idempotent, but it
      appears to me that it's a constraint that deserves to be given more
      importance, by using PUT. (By the way, to refer to last week's thread,
      my understanding of POST not being idempotent is that N+1 times the same
      request may or may not have the same effect as just one.)


      I'm not sure which one is right between PUT and POST (in both cases),
      although I tend to think at least the 'tentative' PUT ought to be a
      POST. Any comments appreciated.


      Best wishes,


      Bruno.
    • mike amundsen
      i d consider modeling it like this: -- create a new (inactive) request C: POST http://example.org/Factory S: HTTP 200 with document
      Message 2 of 4 , Jul 5, 2007
      • 0 Attachment
        i'd consider modeling it like this:

        -- create a new (inactive) request
        C: POST http://example.org/Factory <newItemReq />
        S: HTTP 200 with <itemReq /> document and Location:http://example.org/Item/1

        -- activate existing request
        C: HTTP PUT to http://example.org/Item/1 containing modified <itemReq
        /> that has the activate information
        S: HTTP 200 OK.
        S: HTTP 404 Not Found (for invalid request ids)
        S: HTTP 410 Gone (for expired/lost requests)

        mamund

        > (phase 1: tentative)
        > C: HTTP PUT to http://example.org/Factory containing <newItemReq />
        > S: HTTP 201 with Location: http://example.org/Item/1
        >
        > (phase 2: activation)
        > C: HTTP PUT to http://example.org/Item/1 containing <resActivator />
        > S: HTTP 200 OK.

        <snip>
        On 7/5/07, Bruno Harbulot <Bruno.Harbulot@...> wrote:
        > Hello,
        >
        >
        > Apologies if I revive last week's thread about POST being idempotent or
        > not, but it got me confused on the choice between using POST or PUT in
        > the system on which I'm working, and idempotent messages matter in this
        > case.
        >
        </snip>
      • Mike Dierken
        When you use PUT, the URI sent in the request is the identifier of the content within that message. So doing the following would replace the factory with a
        Message 3 of 4 , Jul 5, 2007
        • 0 Attachment
          When you use PUT, the URI sent in the request is the identifier of the
          content within that message.
          So doing the following would replace the 'factory' with a 'newItem' blob:
          C: HTTP PUT to http://example.org/Factory containing <newItemReq />

          One difference between PUT and POST is that with PUT the client already
          knows the intended URI (the 'id') of the data being submitted. With POST,
          the server might create a new identifier for the submitted data and the
          clients needs to receive the response to learn what that identifier is.

          In order to activate the resource (acknowledge to the server that the client
          received the response) you are sending a PUT to the new resource with a
          particular content type. Sending different content types via PUT gives rise
          to really long discussion threads on rest-discuss and I generally avoid
          that.

          Perhaps you could request a new blank resource be created via a POST to the
          factory, then populate that blank resource via a PUT with the actual content
          to be stored - this initializing PUT on a blank resource would be idempotent
          so simple retries would help get past some network failures. If the factory
          POST didn't work, the client can retry but a different identifier would be
          created in that case - which is similar to how your design allows for
          un-acknowledged resouces to fade away and similar to what Mike Amundsen
          suggested as well.




          > -----Original Message-----
          > From: rest-discuss@yahoogroups.com
          > [mailto:rest-discuss@yahoogroups.com] On Behalf Of Bruno Harbulot
          > Sent: Thursday, July 05, 2007 11:48 AM
          > To: rest-discuss@yahoogroups.com
          > Subject: [rest-discuss] PUT or POST, idempotent for the application
          >
          > Hello,
          >
          >
          > Apologies if I revive last week's thread about POST being
          > idempotent or not, but it got me confused on the choice
          > between using POST or PUT in the system on which I'm working,
          > and idempotent messages matter in this case.
          >
          >
          > We've designed a system (which I believe complies with the REST
          > principles) that relies on a client interacting with a
          > resource to create other resources.
          >
          >
          > To summarise how this system works, a client can ask the
          > Factory resource to create Item resources. The process of
          > creating an Item resource must follow two constraints:
          > - at the end of the process, the client must have created
          > one Item resource and must know its URI;
          > - at the end of the process, the Factory resource must
          > know that the client knows the new Item resource URI.
          >
          > Initially, we assume the client has been configured to know
          > the URI of the Factory: http://example.org/Factory.
          >
          > The protocol we use is as follows (the numbers in the URIs are just
          > examples):
          >
          > (phase 1: tentative)
          > C: HTTP PUT to http://example.org/Factory containing <newItemReq />
          > S: HTTP 201 with Location: http://example.org/Item/1
          >
          > (phase 2: activation)
          > C: HTTP PUT to http://example.org/Item/1 containing <resActivator />
          > S: HTTP 200 OK.
          >
          >
          > An HTTP GET on http://example.org/Factory returns a list of
          > all the Items that have been created and 'activated' (i.e. of
          > which the Factory knows that the client knows their address).
          > If the Factory never receives the second PUT, the Item
          > resource is not the list document. (Optionally, if the client
          > interacts later with the Item resource, this may activate
          > this resource anyway). Item resources that are not activated
          > may be discarded at any time by the Factory (in which case
          > the client would have to re-start the entire process.)
          >
          > Here is an example of what could go wrong and how this would
          > be handled:
          >
          > (phase 1: tentative)
          > C: HTTP PUT to http://example.org/Factory containing <newItemReq />
          > S: HTTP 201 with Location: http://example.org/Item/1
          > - the connection is lost and the new URI never reaches the client.
          >
          > (phase 1: another attempt)
          > C: HTTP PUT to http://example.org/Factory containing <newItemReq />
          > S: HTTP 201 with Location: http://example.org/Item/2
          >
          > (phase 2: activation)
          > C: HTTP PUT to http://example.org/Item/2 containing <resActivator />
          > S: HTTP 200 OK.
          > - the client knows the URI of the Item it has successfully
          > created, and the factory knows that the client knows.
          >
          >
          >
          > The 'activation' PUT is idempotent because sending it N+1
          > times has the
          > same effect as sending it just once.
          >
          > I also think the first 'tentative' PUT is idempotent, although it is
          > more subtle. Effectively, whatever the URI returned in the tentative
          > phase is does not matter, either to the client or to the
          > factory. When
          > taking into account the two phases, sending N+1 'tentative' PUT + an
          > 'activation' has the same result as sending only one tentative PUT
          > followed by an activation: only one Item resource is
          > activated and both
          > the client and the server know about its URI.
          >
          >
          > When reading Section 9.5 and 9.6 of RFC 2616, my use of PUT
          > here is not
          > appropriate, and it should probably be POST, in both cases, for two
          > different reasons:
          > - the 'tentative' PUT clearly does not comply with "the
          > URI in a PUT
          > request identifies the entity enclosed with the request" (in
          > Section 9.6);
          > - the 'activation' PUT might rather be considered as an
          > "annotation
          > of existing resources" (in Section 9.5).
          >
          >
          >
          > I'm tempted to change these two PUTs into POSTs. However, I
          > quite like
          > the fact that PUT is intended to be idempotent. I believe the
          > fact that
          > a request is guaranteed to be idempotent is more important
          > than "the URI
          > in a PUT request identifies the entity enclosed with the
          > request" when
          > designing distributed systems.
          > Obviously, the use of POST in this system may be idempotent, but it
          > appears to me that it's a constraint that deserves to be given more
          > importance, by using PUT. (By the way, to refer to last
          > week's thread,
          > my understanding of POST not being idempotent is that N+1
          > times the same
          > request may or may not have the same effect as just one.)
          >
          >
          > I'm not sure which one is right between PUT and POST (in both cases),
          > although I tend to think at least the 'tentative' PUT ought to be a
          > POST. Any comments appreciated.
          >
          >
          > Best wishes,
          >
          >
          > Bruno.
          >
          >
          >
          > Yahoo! Groups Links
          >
          >
          >
        • A. Pagaltzis
          Hi Bruno, ... See http://bitworking.org/news/201/RESTify-DayTrader Short answer: the client POSTs a request, upon which the server creates a ticket of the form
          Message 4 of 4 , Jul 6, 2007
          • 0 Attachment
            Hi Bruno,

            * Bruno Harbulot <Bruno.Harbulot@...> [2007-07-05 20:50]:
            > I'm tempted to change these two PUTs into POSTs. However, I
            > quite like the fact that PUT is intended to be idempotent. I
            > believe the fact that a request is guaranteed to be idempotent
            > is more important than "the URI in a PUT request identifies the
            > entity enclosed with the request" when designing distributed
            > systems.
            > Obviously, the use of POST in this system may be idempotent,
            > but it appears to me that it's a constraint that deserves to be
            > given more importance, by using PUT. (By the way, to refer to
            > last week's thread, my understanding of POST not being
            > idempotent is that N+1 times the same request may or may not
            > have the same effect as just one.)
            >
            > I'm not sure which one is right between PUT and POST (in both cases),
            > although I tend to think at least the 'tentative' PUT ought to be a
            > POST. Any comments appreciated.

            See http://bitworking.org/news/201/RESTify-DayTrader

            Short answer: the client POSTs a request, upon which the server
            creates a ticket of the form

            {$uuid}:{sha1(concat($uuid,$some_secret))}

            The response contains this ticket in the Location of the form

            http://example.org/Item/{$ticket}

            which the client is expected to PUT to.

            Validating such a ticket relies on knowing the secret only, so
            the server can do it without the necessity for any per-ticket
            storage.

            You could use GET with this scheme if you really wanted to make
            the first request idempotent, but then I’d worry about broken
            intermediaries that might cache the response despite any number
            of headers to the contrary. POST provides an easy reliable way
            to pierce caches.

            Regards,
            --
            Aristotle Pagaltzis // <http://plasmasturm.org/>
          Your message has been successfully submitted and would be delivered to recipients shortly.