Re: URI design, part 2

"Eric J. Bowman" <[email protected]>
Newsgroups gmane.comp.web.services.rest
Organization Bison Systems Corporation
Message-ID <[email protected]>
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
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.