[plt-scheme] Implementing web services
John Clements wrote:
> Someone tell me I'm mistaken: it appears to me that REST is simply
> continuation-based web programming with the additional restriction that
> there be only a finite set of possible continuations; the easiest way
> to achieve this is to allow only tail calls. So in principle, cps-ing
> achieves REST. In common use, however, maintaining a continuation as a
> POST-style argument is un-idiomatic, slow, and insecure, so you need to
> severely restrict the possible size of the continuation argument.
>
> Is that a fair summary? Did I just recapitulate the slides I skimmed?
I'd say that's correct as far as it goes (in principle), but there's
more to it than just restricting the possible size of the continuation
argument. The ideal goal (often not achieved) for a REST app is to
structure it so that continuations can be represented as nothing more
than URLs which don't depend on any session-specific state.
If you can email a URI to your friend and have it work for her, and if
it continues to work in the future, then that's a pretty RESTful URI.
If you take that ability as a goal throughout an application, it implies
all sorts of things about the structure of the application and its
continuations.
Some of those things are probably what Shriram was thinking of when he
wrote "incredibly hard to implement in practice if you really want to be
true to Fielding's criteria."
I'm not sure I'd agree about "incredibly hard", unless writing in
inverted-control style counts, or fighting with frameworks that aren't
designed to support REST. But it's not that hard if you design the
application to fit REST guidelines. There can be benefits to doing
that. It does tend to involve more work, though.
A problem with automatically-generated continuations, as in send/suspend
etc., is that it can be difficult to limit them to just the relevant
state. They're also not intended to be persistent.
To use a simple concrete example, say we extend the "add.ss" example
servlet to maintain a running total of the numbers that have been
entered so far. I then patiently sit at my browser and add up a few
hundred numbers. Now I want to bookmark one of the result pages, or add
its URI to a wiki, or email the URI to a colleague.
With a continuation-based server, one runs into a slew of issues at this
point:
* The dependency on a POST request prevents its use in this way. POST
requests are OK for submitting data, but in REST terms the resulting
page should be identified only by its URI. You can of course address
this with the post-redirect-get pattern. This can of course be done
easily enough, but it points out one way in which applications have to
be structured to support REST.
* The continuation (and its URI) isn't persistent - e.g. it can time
out, and it doesn't survive server restarts. This is a big one which
effectively eliminates non-persistent continuations as a candidate for
development of REST apps.
* In a slightly more sophisticated application which supports user
logins, an identifier for the logged-in user would typically end up
being stored in the continuation, unless you take active steps to
prevent it. That information, along with various other kinds of
session-related info, is orthogonal to the resource being referenced by
a URI, and you don't want the URI to somehow "contain" this information
and thus either limit its usefulness, or even compromise security.
* etc.
If you think of REST as identifying a set of tradeoffs (at least,
Fielding's paper does that), and giving a name to a region in that
tradeoff space, then continuation-based servers as currently conceived
tend to overlap the edges of that space, at best. Although in
principle, the CPS+lambda-lifting+defunctionalization transformation
gets you to a similarly structured application, that's not enough by itself.
Anton