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

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

Expand Messages
  • 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 1 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 2 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 3 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 4 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.