Ian Bicking: the old part of his blog

REST in more than one request

Thinking more about post on continuation-based frameworks, and reading through this interesting conversation, it occurs to me that RESTful encapsulation is being limited to one request, stateless, and pushing a lot of data into one HTTP call. I think this is too limiting. Encapsulation is nice, but if you are willing to give up synchronous completion of the encapsulated activity, then multiple requests aren't so bad.

The example that came up in that conversation is an ecommerce site. In that model, the product pages can and probably should be RESTish. But the ordering process isn't so much. There's multiple steps. A variable number of steps probably, and sometimes you have to go back a step (e.g., invalid credit card). It's interactive, and highly stateful. Not very REST, maybe good for continuations.

Well, lets pick that apart some more. The items you purchase are all RESTy. Everyone sees the same items.

The shopping cart is pretty easy to imagine in a REST form. You pop things in, you pop things out.

OK, so the user hits "checkout", and you grab the cart contents from the REST cart. And you grab the HTML representation of the contents from the cart. And then you have an "app" that lets you see the total, remove things, etc. Is that app REST? No... I don't even know exactly what that would mean if it was REST. This is where I think people can go down the cargo cult path, because they are looking at how to make that RESTy, and so they worry about what the URI for the delete action looks like.

But if you step back just a bit, that app can look RESTish too. You tell the app where the cart is. You tell the app what to do when you are finished. Then the app is a service; when you send the user's browser over to the app, you are calling that service, and you'll get your response when the app directs the user's browser to the next step in the process.

Unlike what is typically described as a service, attaining the result -- an actual checkout -- takes many requests, not one. And it involved the user's browser. But it can be encapsulated. So can the payment, and other pieces. Is the result going to be as tweaked out as Amazon's checkout form? Probably not; the application boundaries might be quite noticeable to users (though there is progress to be made there, and Ajax techniques can help a great deal). The user might not be able to edit all the pieces at once. There's probably a bunch of glue; glue is overhead, RESTful or not.

And that form/app for actually managing your shopping cart contents? Yeah, that can be continuation based. But why? It's not a complex application, you don't need a clever framework. Once you have a clever framework you're going to mix these problems together and solve them all at once, because you have to justify the framework, and there's no way in hell you can do that for some silly little form that lets you change what's in your cart.

Maybe there needs to be some language for non-service-oriented REST; REST where the browser is a peer, not just a viewer into the consolidation of services on the server side. Or another term, maybe "REST" shouldn't be overloaded so much. But something... browser-based web services?

Created 13 Apr '06

Comments:

Good stuff:

... it occurs to me that RESTful encapsulation is being limited to one request, stateless, and pushing a lot of data into one HTTP call

I got that feeling too. I think the original concept was that state should either be stored on the client or on the server as a resource. There's no rule that says you can't have state on the server, just that it should be behind a distinct resource / URL.

But the ordering process isn't so much. There's multiple steps. A variable number of steps probably, and sometimes you have to go back a step (e.g., invalid credit card). It's interactive, and highly stateful. Not very REST, maybe good for continuations.

I'd argue that processes like this illustrate RESTs strengths quite well since they use hypermedia as the engine of application state. The next/previous links driving the process either way illustrate this fundamental aspect of RESTful interaction. I believe your point was that most continuation based frameworks break a few rules when they keep state on the server in the form of stack frames as opposed to moving everything back to the client but that's just one aspect of REST.

You can build stateful processes using REST, you just have to put state behind URIs if you're storing it on the server, which as you've pointed out is often the better solution.

And then you have an "app" that lets you see the total, remove things, etc. Is that app REST? No... I don't even know exactly what that would mean if it was REST. This is where I think people can go down the cargo cult path, because they are looking at how to make that RESTy,

I don't see how that's not RESTy? If a user's cart has a distinct resource on the server and the items in the cart also have distinct resources and manipulating the items in the cart use basic RESTful interaction what's not RESTy? REST doesn't mean a set / constant / global resource space that can never be modified. It just means that everything important should have a distinct URL. The URL can be ugly:

http://shopping.com/cart.php?user=ianb

That's completely RESTful. Here's what's not:

http://shopping.com/cart.php

... and then relying on session state or cookies to determine whose cart it is.

and so they worry about what the URI for the delete action looks like.

The delete action doesn't have a URL - the item has a URL. The delete action is an interaction and it looks like this with AJAX/other capable HTTP client libraries:

DELETE http://shopping.com/cart.php?user=ianb&item=3452 HTTP/1.1

It looks like this with forms:

POST http://shopping.com/cart.php?user=ianb&item=3452 HTTP/1.1
...

action=delete

I think the key thing to take away from all this is that state on the server is fine as long as you're putting it behind a URI and then allowing the client to modify it using the universal interface.

And that form/app for actually managing your shopping cart contents? Yeah, that can be continuation based. But why? It's not a complex application, you don't need a clever framework. Once you have a clever framework you're going to mix these problems together and solve them all at once, because you have to justify the framework, and there's no way in hell you can do that for some silly little form that lets you change what's in your cart.

Amen.

Maybe there needs to be some language for non-service-oriented REST; REST where the browser is a peer, not just a viewer into the consolidation of services on the server side. Or another term, maybe "REST" shouldn't be overloaded so much. But something... browser-based web services?

See, this is where I'm getting the feeling that you've been reading the wrong material on REST. If you're reading stuff that says REST is about "invoking services" using name/value pairs instead of posting XML (WS), then that shit is just wrong. I don't understand where the insinuation that the client is just a "viewer" or that the server is exposing "services" is coming from. None of this is based in REST. REST is all about simple resource representations, identified by unique identifiers (URLs), interlinked using references to each other, and manipulated using a small and universal set of basic verbs. REST is "resource oriented", not "service oriented". There's no concept of a "service", it's resources all the way down.

# Ryan Tomayko

and so they worry about what the URI for the delete action looks like.

The delete action doesn't have a URL - the item has a URL. The delete action is an interaction and it looks like this with AJAX/other capable HTTP client libraries:

DELETE http://shopping.com/cart.php?user=ianb&item=3452 HTTP/1.1

It looks like this with forms:

POST http://shopping.com/cart.php?user=ianb&item=3452 HTTP/1.1
...

action=delete

Well, it probably looks more like:

POST http://shopping.com/cart.php?user=ianb HTTP/1.1
...

action=update&item_3452_amount=0&item_3841_amount=3&item_3841_delete=Delete

Or whatever other details come from the way the HTML form is designed. Oldschool HTML forms are okay, but they do often mean tight coupling between the form and the action. So the RESTful, stable interface isn't the delete action (at least not the one the management app uses), it's some other interface.

See, this is where I'm getting the feeling that you've been reading the wrong material on REST. If you're reading stuff that says REST is about "invoking services" using name/value pairs instead of posting XML (WS), then that shit is just wrong. I don't understand where the insinuation that the client is just a "viewer" or that the server is exposing "services" is coming from. None of this is based in REST. REST is all about simple resource representations, identified by unique identifiers (URLs), interlinked using references to each other, and manipulated using a small and universal set of basic verbs. REST is "resource oriented", not "service oriented". There's no concept of a "service", it's resources all the way down.

I don't think the cart management app will be RESTful, nor do I see any reason it needs to be. It just doesn't matter. It doesn't really matter what the HTML forms are that the cart management uses. When you check out, you redirect the user to that app. When they are finished managing, the management app redirects them to the next step. What happens between those doesn't matter. Nobody should care if the management app uses RESTful principles internally.

Browser-based APIs are more concerned about where the browser goes, not what it sees.

# Ian Bicking

Well... maybe I didn't figure out quite what my point was there. The point of a cart management app is that it speaks to the browser, it speaks POST and HTML. It interacts. It's not an atomic resource, it's really an interactive application that speaks to a browser. There's no resource there.

# Ian Bicking

Now we're getting somewhere...

Well, it probably looks more like:

action=update&item_3452_amount=0&item_3841_amount=3&item_3841_delete=Delete

Indeed.

I don't think the cart management app will be RESTful, ...

I see what you're saying now. The example above is actually still RESTful in that you're not breaking any hard rules directly (so long as those name/value pairs are in a POST body and not on a GET/URL). I think we're 1.) tripping into the area of taste/style and 2.) trying to determine whether manipulating resources directly is preferable to manipulating resources using what the Atom Publishing Protocol calls "collection resources". e.g. You can post to a "collection resource" and manipulate multiple other resources as a result. There's nothing in REST that disallows or even discourages this that I'm aware of. As you've shown, this is an extremely common practice on the web circa 2006.

I think I'm getting a better idea of the behavior you're labeling cargo cultish though. I don't think it's REST, I think it's more like "individual resource orientedness" or something; the idea that every interaction must be performed through specific individual resources, that interactions on collection resources are "bad style," and that URLs that look like "shopping.com/ianb/cart" offer substantial benefits over URLs that look like "shopping.com/cart.php?user=ianb". I think it's fairly safe to call these principals misguided if not harmful.

... nor do I see any reason it needs to be. It just doesn't matter.

It matters if there's value in interacting with the cart items outside of the one simple cart interface page. For example, if the cart had an "API" or if you wanted a cart that contained items from 5 different shopping sites, or if you just wanted to remove or view cart items on an item-by-item basis, etc. But all of these scenarios require some additional requirement beyond the basic shopping cart page so one could argue that building out a full resource hierarchy is a form of pre-mature optimization and breaks basic principals like Unnessary Until Proven Required.

Overall I think I understand where you're coming from a bit better and I'd agree that the resource based approach should be used because it's valuable, not because it's cool.

# Ryan Tomayko