Re: RESTful order-status API (was: URI design, part 2)

"Eric J. Bowman" <[email protected]>
Newsgroups gmane.comp.web.services.rest
Organization Bison Systems Corporation
Message-ID <[email protected]>
+1 to the other answers you've gotten.  Except...

REST is about optimizing the hell out of GET.  The hypertext containing
the PUT control is one place to GET the order status.  But, why cache-
expire the entire record when only one string is changed, multiple times
after the order is placed and becomes static?  A RESTful order-status
API should separate the dynamic aspects of order processing from the
static, as sub-resources, and manipulate *those* to alter a dynamic
representation of the static order.  This becomes especially efficient
when, say, a CC is rejected and the customer needs to enter another one.

Consider PUT /orders/1/status with strings like placed, processing,
pending, and the tracking # from the shipper -- I'd even consider
application/xml and application/json acceptable media types for a
snippet like this, of course not for the hypertext control defining the
PUT.  I'd never PUT 'canceled', I'd use DELETE as Jan described, which
would trigger a reshelving-fee transaction, with /status returning
reshelving on 200 OK, before /orders/1* return 410 Gone, indicating the
transaction has been fully reversed including by the inventory system.

Using code-on-demand to fill in the current status on the PUT control
exposes a status API which may be utilized many different ways (push,
poll, etc.), allowing for serendipitous re-use.  The downside of being
an additional round-trip is mitigated by using compression such that the
/status 200 OK response fits in one IP packet.  Note that XForms may be
used to make this code declarative, avoiding the optional constraint.

This thread isn't about URI design at all, in fact it's irrelevant to
this discussion about hypertext-driven application state, as is method
selection. Also RESTful: /CRMapp?order=1&query=status on GET, and
/CRMapp?order=1&status=canceled on POST using application/x-www-form-
urlencoded, if we assume the hypertext constraint is met, which is what
this thread is really about.

Then we can discuss the pros and cons of various media types which can
implement a RESTful status API, regardless of how the shopping cart is
implemented.  If you're working with making a legacy system more
RESTful over time, you may want HTML 4, JS and POST.  If this is
greenfield, you may consider XForms w/ PUT and DELETE.  Or, use HTML 5
if this is a Web system, not sure where it is regarding PUT/DELETE, but
it really doesn't matter...

The key is the architectural consideration of using subresources for
dynamic elements like order status, allowing the order itself to become
sticky in the client-side cache, while also allowing manipulation of
that resource to occur in one-IP-packet round-trips.  Optimizing
PUT/POST/PATCH doesn't amount to much in the grand scheme of things,
what counts is optimizing GET by making static all those bytes which
make up the order being processed, and manipulating its subresources.

The hypertext interface doesn't even have to reflect the strings
in /status, it could be a graphical progress bar followed by e-mailing
the tracking number (instead of, or in addition to, displaying it).  Or,
the strings in /status 200 OK could be numerals, whose semantics are
conveyed by the PUT control or other hypertext conveying order status.

Always remember REST is an architectural style, not implementation
guidelines.  If you take one thing from it, it should be "optimize GET
to maximize caching."  Then, any implementation mistakes you make are
correctable down the line, instead of coming here and being told to go
back to the drawing board -- iow, if you've separated static from
dynamic as an architectural pattern, then we can make changes to URIs
and methods based on what media types are most appropriate for your
application, because that'll be bikeshedding if you get your resources
right.

I prefer developing REST systems in XForms, makes it easy to separate
static from dynamic in declarative code, to get a handle on what your
resources *are* and how they relate to one another.  I call this
hypertext-constraint-centric development.  The result is a hypertext API
which may then be implemented any way it needs to be, letting the
implementation requirements dictate the system's ultimate hypertext, URI
allocation scheme, and media types if (most likely) XForms isn't
appropriate.  I may hate my HTML 4 implementations' URIs and methods,
but the underlying systems are implicitly RESTful and thus easy to
upgrade over time, as new hypertext technology emerges and matures.

-Eric

On Fri, 30 Nov 2012 10:45:26 -0800
Erik Wilde <[email protected]> wrote:

> +1 on this, it probably would be a good mapping of domain
> interactions to HTTP verbs.
> 
> On 2012-11-30 10:43 , Jan Algermissen wrote:
> >
> > On Nov 30, 2012, at 7:08 PM, Nicholas Shanks
> > <[email protected]> wrote:
> >
> >> On 30 Nov 2012, at 13:15, Max Toro wrote:
> >>
> >>> Thanks for your answers, it's pretty much what I had in mind.
> >>>
> >>> I want to discuss a second example:
> >>>
> >>> a)
> >>> POST /orders/1/cancel
> >>>
> >>> vs.
> >>>
> >>> b)
> >>> PATCH /orders/1
> >>>
> >>> canceled=true
> >>>
> >>>
> >>> Does REST say anything in favor or against these two designs?
> >>
> >> REST says "Do 'b', never 'a'." Sorry!
> >
> > Yes, right.
> >
> > If it suits your use cases, consider:
> >
> > DELETE /orders/1
> >
> > Which might well result in the order being moved to a
> > cancled-orders collection. IOW, it need not be erased entirely.
> >
> > Jan
> >
> >
> >
> >
> >
> >> The simple rule is URIs are for nouns, HTTP methods are for verbs.
> >>
> >> You could get away with this though:
> >>
> >> POST /orders/1
> >> cancelled=true
> >>
> >> Originally, POST was intended to mean "post a reply" the same as
> >> it's NNTP namesake/predecessor. Now, though, the authors of HTTP
> >> concede that it's modern meaning is "Hey, server, use these data
> >> (request body) to perform some action to this resource (uri)"
> >>
> >> As such, by POSTing to /orders/1 you are at least getting the
> >> resource part of the API right, even if you are lacking the
> >> semantics of a PATCH request.
> >>
> >>> Personally, I would never do 'b' because it's simply hard to
> >>> implement with the tools I use. Also, isn't it a case of
> >>> tunneling? 'Cancel' is an action that does more than simply
> >>> update a resource.
> >>
> >>
> >> I wouldn't call it tunnelling, tunnelling would be something like:
> >>
> >> POST /orders/1
> >>
> >> _method_override="DELETE"    // could also be custom HTTP header
> >>
> >> If the "cancel" action is just updating a resource state, rather
> >> then, say, DELETEing the resource, then you could even do
> >> something like:
> >>
> >> PUT /orders/1/cancelled
> >> true
> >>
> >> (again, use POST if you can't PUT)
> >>
> >> and correspondingly:
> >>
> >> GET /orders/1/cancelled
> >>
> >> => "true"
> >>
> >> GET /orders/2/cancelled
> >>
> >> => "false"
> >>
> >> (or 1/0, yes/no, … however you wish to represent it)
> >>
> >>
> >> For reference, stackoverflow.com is a good place to go with these
> >> sorts of questions. Many have already been asked in various forms,
> >> you'll find the answers already provided.
> >>
> >> — Nicholas.
> >>
> >>
> >> ------------------------------------
> >>
> >> Yahoo! Groups Links
> >>
> >>
> >>
> >
> >
> >
> > ------------------------------------
> >
> > Yahoo! Groups Links
> >
> >
> >
> 
> -- 
> erik wilde | mailto:[email protected]  -  tel:+1-510-2061079 |
>             | UC Berkeley  -  School of Information (ISchool) |
>             | http://dret.net/netdret http://twitter.com/dret |
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.