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

Re: [rest-discuss] URI design, part 2

Expand Messages
  • Max Toro
    Did not choose DELETE because cancel does not delete the resource, it executes some logic which in the end sets it s status field to Canceled. The
    Message 1 of 28 , Dec 1, 2012
    • 0 Attachment
      Did not choose DELETE because cancel does not delete the resource, it
      executes some logic which in the end sets it's status field to
      Canceled.
      The implementation of PATCH with a body 'status=Canceled' can be
      tricky if you also accept changes to other fields, which may or may
      not have some logic associated to them. I think that using a
      subresource as Nicholas Shanks suggested is a good solution, e.g.

      PUT /orders/1/status

      Canceled

      The implementation can do something like this:

      switch (value) {
      case "Canceled":
      cancelOrder(id);
      ...
      }
      --
      Max Toro


      On Sat, Dec 1, 2012 at 2:58 PM, Erik Wilde <dret@...> wrote:
      > hello max.
      >
      >
      > On 2012-12-01 08:17 , Max Toro wrote:
      >>
      >> Thanks for you answer Erik. I don't want to repeat myself, so please
      >> see my answer to Eric, I'd love to get your comments as well. Rather
      >> than good or bad I'd like to determine if my example is REST or not.
      >
      >
      > i guess most people agree that the only reasonable answer to a question such
      > as "is URI X RESTful" is: "tell me more about your design."
      >
      > i'd like to get one tiny bit of clarification from you: when saying you have
      > a resource X/operation, did you choose "cancel" on purpose as something that
      > could be mapped to a DELETE X fairly easily, or do you also consider
      > something such as X/additem, where the hypothetical operation would not
      > delete the resource, but change its status outside of the CRUD realm?
      >
      > thanks,
      >
      > dret.
    • Mike Schinkel
      ... +1 As an aside you ll find maintenance and validation easier if your status values are all lowercase (all upper would be okay too, but uglier.) Has nothing
      Message 2 of 28 , Dec 1, 2012
      • 0 Attachment
        On Dec 1, 2012, at 9:21 PM, Max Toro <maxtoroq@...> wrote:
        > PUT /orders/1/status
        > Canceled

        +1

        As an aside you'll find maintenance and validation easier if your status values are all lowercase (all upper would be okay too, but uglier.)

        Has nothing to do with REST, it's just easier to deal with when you don't have to worry what is the proper casing of status values. FWIW.

        -Mike
      • Matt McClure
        ... This seems like a really important point. As I started reading about hypermedia APIs, the authors seemed to be evangelizing the benefit that server
        Message 3 of 28 , Dec 2, 2012
        • 0 Attachment
          On Sat, Dec 1, 2012 at 8:30 AM, Erik Mogensen <erik@...> wrote:
          But this is still not enough to determine if a system adheres to the constraints: For even though the server provides such hypermedia controls, media types and does everything "by the book", it is still up to the *client* to actually *use* these hypermedia controls.  In fact it is up to the author of the agent itself.

          If you write code in the client that hard wires a button called "cancel" to the "POST /orders/1/cancel" HTTP request then the client isn't really honouring the hypermedia controls laid out above.  If, however, it _soft wires_ the same button _because_ of the hypermedia control above, then you're doing it "more right" I would say.  The point is that the client should be written in such a way that it uses _only_ the hypermedia controls that it receives at run-time.

          This seems like a really important point. As I started reading about hypermedia APIs, the authors seemed to be evangelizing the benefit that server programmers could change URIs as requirements evolved. But it seems you can only realize that benefit easily if you can guarantee that all your clients use the hypermedia controls, or that you force the issue by breaking clients that aren't honoring that agreement. Hypermedia APIs seem to raise the expectations on client programmers more than for server programmers.

          As a server programmer, I'm interested to find great examples of hypermedia APIs (and ecosystems, documentation, etc.) that help their client programmers do the right thing.

          Even then, if you can't prevent client developers from "deep linking" into your API, how do you handle breaking changes for those clients?
        • Erik Wilde
          hello matt. ... this is a very good question. one important aspect is that it s always bad if clients are tested against just one implementation. server
          Message 4 of 28 , Dec 2, 2012
          • 0 Attachment
            hello matt.

            On 2012-12-02 08:44 , Matt McClure wrote:
            > Even then, if you can't prevent client developers from "deep linking"
            > into your API, how do you handle breaking changes for those clients?

            this is a very good question. one important aspect is that it's always
            bad if clients are tested against just one implementation. server
            programmers often put quite a bit of effort into designing pretty URIs,
            which is good. but this also lures client programmers into relying on
            those patterns, and as long as you just test against one implementation,
            things often work fine.

            however, often there only is one implementation to test against, so what
            then? something i've been thinking about (and nothing more, and also i
            haven't seen any frameworks supporting this) would be that server
            frameworks could have a "test" switch, that would start serving "ugly"
            and pretty much random URIs, instead of the pretty designed ones. a test
            installation could then be easily provided to client programmers, and
            their code would break very quickly in all places where they took
            shortcuts, instead of following links.

            i haven't seen support for this so far, but it seems to me that in many
            REST-oriented server-side frameworks, this might not be all that hard to
            add. if somebody has seen such a thing in practice, please let me know!

            cheers,

            dret.

            --
            erik wilde | mailto:dret@... - tel:+1-510-2061079 |
            | UC Berkeley - School of Information (ISchool) |
            | http://dret.net/netdret http://twitter.com/dret |
          • Eric J. Bowman
            ... DELETE /orders/1 doesn t have to delete the resource, it can move it to, say, /canceled/1. In which case you re only changing one property of the order
            Message 5 of 28 , Dec 3, 2012
            • 0 Attachment
              Max Toro wrote:
              >
              > Did not choose DELETE because cancel does not delete the resource, it
              > executes some logic which in the end sets it's status field to
              > Canceled.
              >

              DELETE /orders/1 doesn't have to delete the resource, it can move it to,
              say, /canceled/1. In which case you're only changing one property of
              the order "object" on your server -- its mapping. REST isn't CRUD. In
              a hypertext API, it's often best to have different URI paths for the
              same set of server objects, if their policies vary based on a property
              like status...

              Web servers configure policies based on path, so add another URI mapping
              instead of making server logic more complex by trying to apply different
              policies based on parsing content for 'canceled=true'. Try to think in
              terms of hypertext applications instead of serializing objects to
              hypertext -- status isn't a field in a hypertext document in REST when
              its semantics overlap that of HTTP status responses, especially if
              status varies by user role:

              The customer checking /orders/1 knows they've successfully canceled it,
              because their DELETE request responded 200 OK with the order and new
              status in the message body, and that URL now responds to GET with 410
              Gone. The 410 response may include the order as its entity, or not,
              for the customer role.

              Other user roles, i.e. admin, may get redirected to /canceled/1, where
              they are subject to different policies than exist for an active order.
              Admins may DELETE from /canceled to actually delete a canceled order,
              while customers are 403 Forbidden from entering /canceled to begin with.
              Also, just because you're using the DELETE method, doesn't mean the UI
              has to say "delete" on the cancel control.

              >
              > The implementation of PATCH with a body 'status=Canceled' can be
              > tricky if you also accept changes to other fields, which may or may
              > not have some logic associated to them.
              >

              What matters is user intent. Clear intention to cancel an order should
              unambiguously be its own operation from the UI-design perspective; from
              the protocol perspective, this idempotent user action should be made
              explicitly visible on the wire by selecting the most appropriate HTTP
              method.

              Of all manipulations we may allow for an order, this is the only one
              that's self-explanatory without transferring a representation, another
              indication that DELETE has the semantics we're after, provided we don't
              get hung up on having to delete something -- which we don't!

              If, to the requesting user, canceling an order makes it go away, then
              using DELETE meets the self-descriptive messaging and uniform interface
              constraints of REST. What happens to the order is an implementation
              detail, hidden behind the uniform interface. To the world-at-large,
              the traffic pattern of an order cancellation looks like exactly what it
              is, as the principle of generality has been followed.

              The visibility of DELETE allows intermediaries to mark cached copies
              of /orders/1 as stale. This optimization is built-in to the deployed
              infrastructure of the Web, all it does here is ensure the requesting
              user doesn't re-load a stale copy of /orders/1 which fails to reflect
              the results of the action just taken. This can't be done with PATCH,
              even if you can get close by marking the request as idempotent.

              -Eric
            • Eric J. Bowman
              ... Yes, such examples are out there, but in them, /cancel is NOT a resource in the REST sense so they must be some style of RPC... REST, not so much.
              Message 6 of 28 , Dec 3, 2012
              • 0 Attachment
                Max Toro wrote:
                >
                > > Well, what are you expecting to GET from /cancel, or are you just
                > > using that URL to invoke a procedure? If so, then there are a few
                > > places Roy's thesis admonishes against it in Chapter 6 -- the rest
                > > of REST is about positive, rather than negative, reinforcement of
                > > the identification of resources constraint. Suggested reading:
                > > 6.5.2; 6.2.1, in particular: "REST [defines] a resource to be the
                > > semantics of what the author intends to identify."
                >
                > To clarify, /orders/1/cancel is used to modify a resource, using POST.
                > A GET request would result in a Method Not Allowed response.
                >

                Yes, such examples are out there, but in them, /cancel is NOT a resource
                in the REST sense so they must be some style of RPC... REST, not so
                much. Representational State Transfer means just that -- resources are
                manipulated by transferring representations of their current, intended,
                desired etc. state. Chapter 5.4:

                "Requests and responses have the appearance of a remote invocation
                style, but REST messages are targeted at a conceptual resource rather
                than an implementation identifier."

                This example is a REST anti-pattern, as I cannot deduce the current
                (sub)state of the order (active or canceled) by dereferencing the URL
                I'm given for manipulating that (sub)state. Just making a toggle POST
                also fails to transfer any representation of anything, let alone
                application state, and isn't proper HTTP (which can never be proper
                REST).

                REST isn't about optimizing upstream traffic, it's about optimizing GET.
                What advantage does a subresource give when it contains no content from
                the parent resource? My goal with subresources is to increase the cache
                stickiness of their parent resources. Replace the subresource content
                in the parent resource, with a link or a hypertext control linked to the
                subresource. The link or hypertext control remains static, and cached,
                as the content of the subresource varies.

                That's a RESTful pattern, as the subresource now has a representation
                (other than that of the 406 error) we can transfer and manipulate to
                effect change of the parent resource.

                >
                > > Not the semantics of a method invocation. What does /cancel
                > > identify? Sounds to me like a method of tunneling DELETE through
                > > POST which identifies nothing, iow a procedure endpoint, which is
                > > characteristic of various styles but not of the REST style. The
                > > hypertext constraint only makes sense if your resources make sense,
                > > in that their URLs are identifiers rather than endpoints.
                >
                > If I understand correctly, you are saying that if I need to affect a
                > resource then I should use the uniform interface on that resource URI,
                > and not another URI.
                >

                Absolutely not! My example changed /order/1 by manipulating /order/1
                /status. The /order/1 resource includes its status, but its 200 OK
                representations only include links to the /status subresource, derived
                from the /order/1 resource such that manipulating a representation
                of /order/1/status updates /order/1 (on the server, you can do anything
                you want; on the client, the cached link/control in /order/1 now returns
                a different value).

                There's no cost to adding a URI like this, nor does it preclude changing
                order status via PUT/PATCH to /order/1. The difference is that /status
                uses REST's uniform interface, unlike /cancel. The /order/1/status URL
                is only presented within a hypertext control which explains how to
                manipulate it -- picture a drop-down list with the current status
                highlighted, meeting the hypertext constraint. You can always GET the
                status of an order even if you don't have a copy of that order, a
                useful separation of concerns beyond just optimizing GET, promoting
                serendipitous re-use.

                >
                > > Which brings us to Chapter 5, and the short answer to your question:
                > > "POSTing to /cancel violates the Identification of Resources
                > > constraint, and is therefore unRESTful." But I've found that just
                > > giving that answer tends to upset folks who've only read Chapter 5,
                > > then they get defensive about why can't they call their API
                > > RESTful, accusations of pedantry follow, and threads devolve into
                > > general ugliness, heheh...
                >
                > After reading that chapter again I'm not sure my example violates
                > anything, but I'd love to get more clarification from you. Is it the
                > use of a verb in the URI? or not using the URI of the resource I'm
                > trying to modify directly?
                >

                The biggest problem, is that an RPC endpoint which has no GET function
                while improperly listening for a method itself as a trigger rather than
                taking action based on the content of the entity required by that method
                and in obeyance of the semantics of that method, is so far away from
                REST that I don't know where to start except by urging that Roy's
                thesis be read in its entirety. Because it's obvious to me that this
                violates the first three uniform interface constraints, making adherence
                to the fourth irrelevant:

                "REST is defined by four interface constraints: identification of
                resources; manipulation of resources through representations; self-
                descriptive messages; and, hypermedia as the engine of application
                state."

                Note that "noun/verb" terminology is not present in the dissertation.
                But, yeah, if your URI is a "verb" you're probably getting REST wrong.
                There is no "cancel" method in the uniform interface. There are two
                basic means of solving this -- one, is refactor your cancel operation
                to use DELETE; two, tunnel your proprietary cancel method through POST.

                http://tech.groups.yahoo.com/group/rest-discuss/message/19210

                Making this operation its own URI doesn't make it more RESTful, as the
                resulting URI is only a resource in the HTTP/URI sense, but not the
                REST sense, of the term. Utilizing subresources to break out more
                dynamic aspects of content and cache them separately is RESTful; if the
                contents of the GET are also allowable content of a PUT then we're
                letting hypertext drive application state instead of listening for POST
                events to trigger server-object methods we've failed to refactor to the
                uniform REST interface.

                -Eric
              • Max Toro
                Thank you very much for your responses Eric. The short answer is (if I understood correctly): POST /cancel is not REST because it lacks visibility, since it s
                Message 7 of 28 , Dec 4, 2012
                • 0 Attachment
                  Thank you very much for your responses Eric.

                  The short answer is (if I understood correctly): POST /cancel is not
                  REST because it lacks visibility, since it's not possible to
                  understand the client's intent by examining the request.

                  Never thought about HTTP/URI resource vs. REST resource, you say that
                  a URI that doesn't implement GET is probably (or always) not REST.
                  --
                  Max Toro


                  On Mon, Dec 3, 2012 at 1:17 PM, Eric J. Bowman <eric@...> wrote:
                  > Max Toro wrote:
                  >>
                  >> > Well, what are you expecting to GET from /cancel, or are you just
                  >> > using that URL to invoke a procedure? If so, then there are a few
                  >> > places Roy's thesis admonishes against it in Chapter 6 -- the rest
                  >> > of REST is about positive, rather than negative, reinforcement of
                  >> > the identification of resources constraint. Suggested reading:
                  >> > 6.5.2; 6.2.1, in particular: "REST [defines] a resource to be the
                  >> > semantics of what the author intends to identify."
                  >>
                  >> To clarify, /orders/1/cancel is used to modify a resource, using POST.
                  >> A GET request would result in a Method Not Allowed response.
                  >>
                  >
                  > Yes, such examples are out there, but in them, /cancel is NOT a resource
                  > in the REST sense so they must be some style of RPC... REST, not so
                  > much. Representational State Transfer means just that -- resources are
                  > manipulated by transferring representations of their current, intended,
                  > desired etc. state. Chapter 5.4:
                  >
                  > "Requests and responses have the appearance of a remote invocation
                  > style, but REST messages are targeted at a conceptual resource rather
                  > than an implementation identifier."
                  >
                  > This example is a REST anti-pattern, as I cannot deduce the current
                  > (sub)state of the order (active or canceled) by dereferencing the URL
                  > I'm given for manipulating that (sub)state. Just making a toggle POST
                  > also fails to transfer any representation of anything, let alone
                  > application state, and isn't proper HTTP (which can never be proper
                  > REST).
                  >
                  > REST isn't about optimizing upstream traffic, it's about optimizing GET.
                  > What advantage does a subresource give when it contains no content from
                  > the parent resource? My goal with subresources is to increase the cache
                  > stickiness of their parent resources. Replace the subresource content
                  > in the parent resource, with a link or a hypertext control linked to the
                  > subresource. The link or hypertext control remains static, and cached,
                  > as the content of the subresource varies.
                  >
                  > That's a RESTful pattern, as the subresource now has a representation
                  > (other than that of the 406 error) we can transfer and manipulate to
                  > effect change of the parent resource.
                  >
                  >>
                  >> > Not the semantics of a method invocation. What does /cancel
                  >> > identify? Sounds to me like a method of tunneling DELETE through
                  >> > POST which identifies nothing, iow a procedure endpoint, which is
                  >> > characteristic of various styles but not of the REST style. The
                  >> > hypertext constraint only makes sense if your resources make sense,
                  >> > in that their URLs are identifiers rather than endpoints.
                  >>
                  >> If I understand correctly, you are saying that if I need to affect a
                  >> resource then I should use the uniform interface on that resource URI,
                  >> and not another URI.
                  >>
                  >
                  > Absolutely not! My example changed /order/1 by manipulating /order/1
                  > /status. The /order/1 resource includes its status, but its 200 OK
                  > representations only include links to the /status subresource, derived
                  > from the /order/1 resource such that manipulating a representation
                  > of /order/1/status updates /order/1 (on the server, you can do anything
                  > you want; on the client, the cached link/control in /order/1 now returns
                  > a different value).
                  >
                  > There's no cost to adding a URI like this, nor does it preclude changing
                  > order status via PUT/PATCH to /order/1. The difference is that /status
                  > uses REST's uniform interface, unlike /cancel. The /order/1/status URL
                  > is only presented within a hypertext control which explains how to
                  > manipulate it -- picture a drop-down list with the current status
                  > highlighted, meeting the hypertext constraint. You can always GET the
                  > status of an order even if you don't have a copy of that order, a
                  > useful separation of concerns beyond just optimizing GET, promoting
                  > serendipitous re-use.
                  >
                  >>
                  >> > Which brings us to Chapter 5, and the short answer to your question:
                  >> > "POSTing to /cancel violates the Identification of Resources
                  >> > constraint, and is therefore unRESTful." But I've found that just
                  >> > giving that answer tends to upset folks who've only read Chapter 5,
                  >> > then they get defensive about why can't they call their API
                  >> > RESTful, accusations of pedantry follow, and threads devolve into
                  >> > general ugliness, heheh...
                  >>
                  >> After reading that chapter again I'm not sure my example violates
                  >> anything, but I'd love to get more clarification from you. Is it the
                  >> use of a verb in the URI? or not using the URI of the resource I'm
                  >> trying to modify directly?
                  >>
                  >
                  > The biggest problem, is that an RPC endpoint which has no GET function
                  > while improperly listening for a method itself as a trigger rather than
                  > taking action based on the content of the entity required by that method
                  > and in obeyance of the semantics of that method, is so far away from
                  > REST that I don't know where to start except by urging that Roy's
                  > thesis be read in its entirety. Because it's obvious to me that this
                  > violates the first three uniform interface constraints, making adherence
                  > to the fourth irrelevant:
                  >
                  > "REST is defined by four interface constraints: identification of
                  > resources; manipulation of resources through representations; self-
                  > descriptive messages; and, hypermedia as the engine of application
                  > state."
                  >
                  > Note that "noun/verb" terminology is not present in the dissertation.
                  > But, yeah, if your URI is a "verb" you're probably getting REST wrong.
                  > There is no "cancel" method in the uniform interface. There are two
                  > basic means of solving this -- one, is refactor your cancel operation
                  > to use DELETE; two, tunnel your proprietary cancel method through POST.
                  >
                  > http://tech.groups.yahoo.com/group/rest-discuss/message/19210
                  >
                  > Making this operation its own URI doesn't make it more RESTful, as the
                  > resulting URI is only a resource in the HTTP/URI sense, but not the
                  > REST sense, of the term. Utilizing subresources to break out more
                  > dynamic aspects of content and cache them separately is RESTful; if the
                  > contents of the GET are also allowable content of a PUT then we're
                  > letting hypertext drive application state instead of listening for POST
                  > events to trigger server-object methods we've failed to refactor to the
                  > uniform REST interface.
                  >
                  > -Eric
                • Jan Algermissen
                  ... Maybe of interest: http://tech.groups.yahoo.com/group/rest-discuss/message/18998 jan
                  Message 8 of 28 , Dec 4, 2012
                  • 0 Attachment
                    On Dec 4, 2012, at 11:40 PM, Max Toro <maxtoroq@...> wrote:

                    > Thank you very much for your responses Eric.
                    >
                    > The short answer is (if I understood correctly): POST /cancel is not
                    > REST because it lacks visibility, since it's not possible to
                    > understand the client's intent by examining the request.

                    Maybe of interest: http://tech.groups.yahoo.com/group/rest-discuss/message/18998

                    jan


                    >
                    > Never thought about HTTP/URI resource vs. REST resource, you say that
                    > a URI that doesn't implement GET is probably (or always) not REST.
                    > --
                    > Max Toro
                    >
                    > On Mon, Dec 3, 2012 at 1:17 PM, Eric J. Bowman <eric@...> wrote:
                    > > Max Toro wrote:
                    > >>
                    > >> > Well, what are you expecting to GET from /cancel, or are you just
                    > >> > using that URL to invoke a procedure? If so, then there are a few
                    > >> > places Roy's thesis admonishes against it in Chapter 6 -- the rest
                    > >> > of REST is about positive, rather than negative, reinforcement of
                    > >> > the identification of resources constraint. Suggested reading:
                    > >> > 6.5.2; 6.2.1, in particular: "REST [defines] a resource to be the
                    > >> > semantics of what the author intends to identify."
                    > >>
                    > >> To clarify, /orders/1/cancel is used to modify a resource, using POST.
                    > >> A GET request would result in a Method Not Allowed response.
                    > >>
                    > >
                    > > Yes, such examples are out there, but in them, /cancel is NOT a resource
                    > > in the REST sense so they must be some style of RPC... REST, not so
                    > > much. Representational State Transfer means just that -- resources are
                    > > manipulated by transferring representations of their current, intended,
                    > > desired etc. state. Chapter 5.4:
                    > >
                    > > "Requests and responses have the appearance of a remote invocation
                    > > style, but REST messages are targeted at a conceptual resource rather
                    > > than an implementation identifier."
                    > >
                    > > This example is a REST anti-pattern, as I cannot deduce the current
                    > > (sub)state of the order (active or canceled) by dereferencing the URL
                    > > I'm given for manipulating that (sub)state. Just making a toggle POST
                    > > also fails to transfer any representation of anything, let alone
                    > > application state, and isn't proper HTTP (which can never be proper
                    > > REST).
                    > >
                    > > REST isn't about optimizing upstream traffic, it's about optimizing GET.
                    > > What advantage does a subresource give when it contains no content from
                    > > the parent resource? My goal with subresources is to increase the cache
                    > > stickiness of their parent resources. Replace the subresource content
                    > > in the parent resource, with a link or a hypertext control linked to the
                    > > subresource. The link or hypertext control remains static, and cached,
                    > > as the content of the subresource varies.
                    > >
                    > > That's a RESTful pattern, as the subresource now has a representation
                    > > (other than that of the 406 error) we can transfer and manipulate to
                    > > effect change of the parent resource.
                    > >
                    > >>
                    > >> > Not the semantics of a method invocation. What does /cancel
                    > >> > identify? Sounds to me like a method of tunneling DELETE through
                    > >> > POST which identifies nothing, iow a procedure endpoint, which is
                    > >> > characteristic of various styles but not of the REST style. The
                    > >> > hypertext constraint only makes sense if your resources make sense,
                    > >> > in that their URLs are identifiers rather than endpoints.
                    > >>
                    > >> If I understand correctly, you are saying that if I need to affect a
                    > >> resource then I should use the uniform interface on that resource URI,
                    > >> and not another URI.
                    > >>
                    > >
                    > > Absolutely not! My example changed /order/1 by manipulating /order/1
                    > > /status. The /order/1 resource includes its status, but its 200 OK
                    > > representations only include links to the /status subresource, derived
                    > > from the /order/1 resource such that manipulating a representation
                    > > of /order/1/status updates /order/1 (on the server, you can do anything
                    > > you want; on the client, the cached link/control in /order/1 now returns
                    > > a different value).
                    > >
                    > > There's no cost to adding a URI like this, nor does it preclude changing
                    > > order status via PUT/PATCH to /order/1. The difference is that /status
                    > > uses REST's uniform interface, unlike /cancel. The /order/1/status URL
                    > > is only presented within a hypertext control which explains how to
                    > > manipulate it -- picture a drop-down list with the current status
                    > > highlighted, meeting the hypertext constraint. You can always GET the
                    > > status of an order even if you don't have a copy of that order, a
                    > > useful separation of concerns beyond just optimizing GET, promoting
                    > > serendipitous re-use.
                    > >
                    > >>
                    > >> > Which brings us to Chapter 5, and the short answer to your question:
                    > >> > "POSTing to /cancel violates the Identification of Resources
                    > >> > constraint, and is therefore unRESTful." But I've found that just
                    > >> > giving that answer tends to upset folks who've only read Chapter 5,
                    > >> > then they get defensive about why can't they call their API
                    > >> > RESTful, accusations of pedantry follow, and threads devolve into
                    > >> > general ugliness, heheh...
                    > >>
                    > >> After reading that chapter again I'm not sure my example violates
                    > >> anything, but I'd love to get more clarification from you. Is it the
                    > >> use of a verb in the URI? or not using the URI of the resource I'm
                    > >> trying to modify directly?
                    > >>
                    > >
                    > > The biggest problem, is that an RPC endpoint which has no GET function
                    > > while improperly listening for a method itself as a trigger rather than
                    > > taking action based on the content of the entity required by that method
                    > > and in obeyance of the semantics of that method, is so far away from
                    > > REST that I don't know where to start except by urging that Roy's
                    > > thesis be read in its entirety. Because it's obvious to me that this
                    > > violates the first three uniform interface constraints, making adherence
                    > > to the fourth irrelevant:
                    > >
                    > > "REST is defined by four interface constraints: identification of
                    > > resources; manipulation of resources through representations; self-
                    > > descriptive messages; and, hypermedia as the engine of application
                    > > state."
                    > >
                    > > Note that "noun/verb" terminology is not present in the dissertation.
                    > > But, yeah, if your URI is a "verb" you're probably getting REST wrong.
                    > > There is no "cancel" method in the uniform interface. There are two
                    > > basic means of solving this -- one, is refactor your cancel operation
                    > > to use DELETE; two, tunnel your proprietary cancel method through POST.
                    > >
                    > > http://tech.groups.yahoo.com/group/rest-discuss/message/19210
                    > >
                    > > Making this operation its own URI doesn't make it more RESTful, as the
                    > > resulting URI is only a resource in the HTTP/URI sense, but not the
                    > > REST sense, of the term. Utilizing subresources to break out more
                    > > dynamic aspects of content and cache them separately is RESTful; if the
                    > > contents of the GET are also allowable content of a PUT then we're
                    > > letting hypertext drive application state instead of listening for POST
                    > > events to trigger server-object methods we've failed to refactor to the
                    > > uniform REST interface.
                    > >
                    > > -Eric
                    >
                  • Eric J. Bowman
                    ... I d phrase it differently: POST /cancel violates self-descriptiveness as user intent cannot be discerned by examining the request. This would hold true
                    Message 9 of 28 , Dec 5, 2012
                    • 0 Attachment
                      Max Toro wrote:
                      >
                      > The short answer is (if I understood correctly): POST /cancel is not
                      > REST because it lacks visibility, since it's not possible to
                      > understand the client's intent by examining the request.
                      >

                      I'd phrase it differently: "POST /cancel violates self-descriptiveness
                      as user intent cannot be discerned by examining the request." This
                      would hold true even if GET /cancel had a 200 OK response. Even that's
                      oversimplifying in that part of the reason POST is wrong here, is
                      because DELETE is right. But, no, I do not believe setting up an URL to
                      listen for POST and taking action not based on anything in the POST
                      request, is ever an example of the REST style, regardless of the nature
                      of the resource.

                      My real short answer is, "POST /cancel doesn't use REST's uniform
                      interface."

                      Neither is it an example of the REST style for POST to have a definition
                      which varies by resource, iow sometimes it works without an entity
                      (method-tunnel listener), sometimes it doesn't (create resource); even
                      if hypertext-driven, such nonstandard method usage inevitably results
                      in coupling between client and server, instead of relying on shared
                      understanding of standardized method semantics. Fixing the POST to have
                      an entity that's ignored might make it valid HTTP and solve this, but it
                      still wouldn't be an example of the REST style, where the requested
                      state change is transferred in the entity (with a few exceptions) -- not
                      defined per resource by the method being tunneled through / triggered by
                      POST.

                      Conceptually, it still violates the identification of resources
                      constraint, which is why it isn't visible regardless of how we implement
                      it in terms of hypertext or method selection. Using the uniform
                      interface means refactoring internal methods like 'cancel' to fit the
                      resource/representation model of REST such that the request methods and
                      response codes used map generically to those of your chosen protocol.
                      Assigning them URIs to toggle with semantically-void messages is simply
                      some other style not encompassed by REST's uniform interface constraint,
                      not something that's superficially fixable by improving visibility or
                      adding a 200 OK response.

                      >
                      > Never thought about HTTP/URI resource vs. REST resource, you say that
                      > a URI that doesn't implement GET is probably (or always) not REST.
                      >

                      More like, "REST resources are concepts, not actions." Just using URIs
                      doesn't bestow compliance with the identification of resources
                      constraint upon a system, it's more nuanced than that. I can't imagine
                      why a bona-fide REST resource would ever deliberately fail to have a
                      retrieval mapping, no.

                      I think the more important takeaway is method selection. We have DELETE
                      in order to avoid such convoluted POST-based cancel mechanisms. It
                      isn't RESTful to use POST when another method's semantics happen to
                      closely describe user intent. From Roy's blog:

                      "POST only becomes an issue when it is used in a situation for which
                      some other method is ideally suited: e.g., retrieval of information
                      that should be a representation of some resource (GET), complete
                      replacement of a representation (PUT), or any of the other standardized
                      methods that tell intermediaries something more valuable than 'this may
                      change something.' The other methods are more valuable to
                      intermediaries because they say something about how failures can be
                      automatically handled and how intermediate caches can optimize their
                      behavior. POST does not have those characteristics, but that doesn't
                      mean we can live without it. POST serves many useful purposes in HTTP,
                      including the general purpose of 'this action isn't worth
                      standardizing.'"

                      http://roy.gbiv.com/untangled/2009/it-is-okay-to-use-post

                      Since DELETE is inherently self-descriptive of user intent to cancel an
                      order, and is already "listened for" rather than requiring an entity be
                      transferred, and has inherent idempotency matching the inherently
                      idempotent user intent captured by a cancel request, DELETE must be the
                      proper method for implementation using HTTP.

                      Now, maybe your media type doesn't support DELETE, in which case
                      contriving a /cancel URI may very well be called for until such time
                      as it does. I won't fault anyone for doing this out of pragmatism, so
                      long as they understand it as a mismatch, inconsistent with the
                      architectural style they're following.

                      REST is a tool which allows you, over time, to make improvements to the
                      architecture you have in accordance with an idealized model. To me,
                      accepting mismatches for what they are, is far more useful than coming
                      up with convoluted explanations for why they aren't, for the sake of
                      buzzword compliance. Change is easier when it's based on having been
                      right all along, rather than based on having to admit error. ;-)

                      -Eric
                    Your message has been successfully submitted and would be delivered to recipients shortly.