← Home

Thinking about RESTful dynamic web applications

"For example, I do want to say, "Welcome, John" on the top of every page once you've signed in. But I'm currently planning on attempting to have only two representations of each page, one for signed in users and one for anonymous. The signed in representation will have some JavaScript that grabs the Welcome greeting and insert it dynamically on the page. If a client doesn't have JavaScript enabled, then they still see they are signed in, because that's one of the two representations sent from the server, but they won't see their name in a welcome message. To me that's a graceful degradation for non-JavaScript clients that I'm willing to accept in exchange for improved cache effectiveness. (The signed in/anonymous representations only work for clients with cookies enabled. Otherwise I have to fall back to URL rewriting, where the caching will be less effective, because I'll have a different URI per resource per session.)"
http://groups.yahoo.com/group/rest-discuss/message/5997

Leaving degradation alone for a moment - how could a Javascript snippet that "grabs the Welcom greeting" look like?

Obviously it would need to be idententical for every client accessing the ressource. We'd otherwise get different ETags and instantly loose the whole caching point. That is, we can't include something like

<script>http://www.domain.com/user/1/welcome.js</script>

for the simple reason that it's different from the URL any other user would be served with.

Probably I'm blind but I can't see any other reasonable way than to use a cookie here. But aren't cookies unRESTfully evil? Luckily there are some statements from highly respected RESTafarians ;) who declare that cookies are ok to use as long they don't mean to store application state on the server. From my point of view there's nothing against it.

Instead of tailoring the whole page on the server (producing uncachable pages) we'd pass the same sceleton (or "shell") page to every client - along with a cookie that does not need to store anything else than a unique ID on the client.

Afterwards the client can pull further content (be it a simple message or full fledged "components") from the server because she now knows how to construct the apropriate URLs:

var url = 'http://www.domain.com/user/' + cookie.userId +
    '/welcome.js';

Again, welcome.js could now be cached - or (in case we'd want to get more nifty) itself be a "shell" pulling further, specialized content.

I don't know if this is what Bill meant by "conversational state" - I'd simply call that a "session" (which has been a recent and very interesting debate on the above mentioned mailing list). The server "initializes" the client (by issuing the cookie) to use certain ressources for further lookups. This "initialization" will remain as long as the cookie remains. There's no particular "state" to be maintained on the server.

The REST FAQ over at blueoxen.net explains it like this:

Interaction is stateless when a single request can be processed without knowing which requests have been made previously. Consider an authenticated request for a person's phone number. You could have a conversation that goes like this:

Me: I would like your phone number, please.
You: Who are you?
Me: I'm your old buddy Frank, don't you recognize me?
You: Oh, well then my number is...

That's a stateful conversation because I supplied my credentials without resubmitting my request. This next conversation is stateless:

Me: I would like your phone number, please.
You: Who are you?
Me: I'm your old buddy Frank, and I would like your
phone number please.
You: Oh, well then my number is....

In our "Welcome John!" example the dialog would look like this:

Client: "Hi! I think you know me by my [username] and
[password]"
Server: "Year, hi again! You'll find your stuff by using
the ID 1."
Client: "Cool. Than please hand me over the welcome message
with the ID 1."
Server: "Ok, here it is: Welcome John!"

As far as I can see two issues remain. One is authorization to restricted ressources. I'd love to use the HTTP auth scheme here also. I've never done so because of the usual problems with it - like being nasty, not styleable, no logout etc. But on the one hand, I think this should be possible to solve with some JS/AJAX style approach. On the other hand it seems as if I'm going to be on Ruby on Rails with my next upcoming project and I don't know about how this would actually fit together.

The other one is degradation.

Ok, as long as we're not going to do any more than display a "Welcome back, John!" message once the user's logged on - well, I'm sure that I'd be able to convince my customers to simply go without that for that 5 to 10% users who might Javascript have turned off.

For some projects a noscript message could do it - like:

<noscript>
    Too bad! With JS turned on, you could [rule the world].
</noscript>

Another approach could have the cachability of the served pages itself depend on whether the client hast JS turned on or not - and serve a different etagged page to people without JS along with the appropriate headers to prevent these pages from being cached at all.

if client.isJsEnabled():
    headers(cachable) + shell page
else:
    headers(no-cache) + classical user-customized page
endif

By the way, from reading this article I think, this same issue evolves with Ruby on Rails concerning these nifty "flash" messages when using page caching.