« Change to REST URLs for Rails 2.0 | Main | The coolest app you never knew was on your hard drive »

March 29, 2007

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/services/trackback/6a00d83451c41c69e200d8341c630153ef

Listed below are links to weblogs that reference The RADAR Architecture: RESTful Application, Dumb-Ass Recipient:

» PragDave nails it. Again. from Just A Summary
REST is easy, its just smart clients using HTTP to the full. Except, as Dave PragDave Thomas points out, browsers arent smart. Theyre just dumb terminals with prettier graphics. And what does that mean? It means that a t [Read More]

» Arquitetura RADAR: Aplicações RESTful, Recebedor Trivial from Balance On Rails
Faz tempo que não faço nenhuma tradução por aqui, mas para não perder o costume esbarrei neste artigo de Dave Thomas. É um texto importante por ajudar a entender o conceito de REST e a sugestão de uma nova arquitetura, uma vez que o novo Rails 1.2 [Read More]

» Morning Coffee 64 from DevHawk
[Read More]

» And then there was... from Tammer Saleh
This has been feeling to me, lately, like the natural progression of things, especially with this sitting just around the corner [Read More]

Comments

Ben Francis

From a pragmatic point of view this makes an awful lot of sense because it's easier to bend your server application to the will of millions of existing web browsers than to change the way browsers work.

However, I wonder whether from an idealistic point of view this would be better addressed in the design of the "dumb browsers" you talk about. The dumb browser doesn't need to be quite as dumb if we don't want it to.

What if XHTML forms and Web Browsers *did* support the PUT and DELETE verbs? I'm not familiar with the reasons that browsers do not already support these HTTP methods, but I do know that the original vision Tim Berners-Lee had of a web browser was of an application which could write data as readily as it could read it.

Maybe it is a user interface problem.

Asbjørn Ulsberg asked what a request/response would like if a web browser wants to GET a resource represented as an HTML form so it can edit the information and then PUT it back to the same URI. In answer to his question, I don't believe we should have a MIME type to put into an Accept header specifically for an HTML form view. It's still HTML after all!

Perhaps the answer is that when HTML is displayed in a browser, if the user has write permission, it is editable in the same way that a document in a word processor is editable, rather relying exclusively on forms for user input. If you've ever used Google Docs you may have noticed that if you click on the title of a document, it becomes editable using JavaScript. There is no separate "edit" and "view" mode, it's all one thing so you don't need to tag ;edit to the end of the URI. The reason web browsers themselves don't work this way is probably because the HTML view is only one representation of a resource and it might be hard to translate changes made by the user to this presentation of the information into changes in the underlying data model. Using forms allows the application designer to restrict user input to specific fields in the underlying data model. This is something which needs more thought because I believe it's also the core reason behind the "offline problem", but that's a different story.

roberthahn writes that "The dumb browser doesn't provide the user with a way of submitting requested Mime types." Well, again, maybe this is a user interface issue with the browsers, maybe they should! Remember that the web is just a collection of resources, HTML is only one representation of those resources.

If "smart" client interface can specify which representation it wants, why can't a user? Maybe a user should be able to choose whether they want to browse the web in plain text, formatted text, or even 2D or 3D vector graphics or a voice representation of a resource. The user agent could allow the user to choose a particular mode in which to browse the web depending on their current environment, and offer alternative representations where they are available. For devices that are only capable of certain modes of interaction with the user (e.g. a voice interface), this could be fixed by the user agent.

We shouldn't entirely dismiss the idea of changing web user agents themselves, just because it is a difficult option.

Ron Phillips

I keep thinking that stylesheets ought to be part of the answer. If I request a representation of a "document" in xml, then displaying it in paragraph format would be one stylesheet, and showing it in an editable page (textareas and such) should be just a different styling of the same data.

I don't think it's truly achievable right now, but isn't that kind of the general idea of stylesheets? So, the REST API would return a 'generic' representation, and it would be up to the requester to also fetch appropriate styling instructions -- or am I completely off-base here?

Dave Thomas

Ron:

I don't think stylesheets get you where you need to go--there's a whole layer of additional stuff needed to drive the user interface (just think about the page framing in a typical web application)

Ron Phillips

Agreed, it's not achievable right now. In theory, though, CSS were advertised as "the answer" for separating presentation and content. I keep hearing discussions about separating presentation and content without any mention of stylesheets, so I guess they're kind of a failure at the level you're talking here.

Thanks for the quick response, and doubly for the article -- it's helped clear up a lot of the "why" questions I had about REST.

Ron

roberthahn

I'm still not completely convinced that you *have* to go the RADAR route to solve the problems you're encountering Dave. When I build apps using the MVC structure that Rails and Camping uses, I put *all* of the business logic in my models (and if some of the logic requires other models, I instantiate access to them in the 'main model' that I'm working with). That means that my controllers are super light, doing the bare minimum to instantiate and kick into gear the model processing, and prep things for the views.

But what if the business logic is complicated, and you want to keep the models looking lean? My thought is that you can pull all the business logic code out into a module that you can include in your model. Likewise, if your interpretation of responsibilities is that business logic should be in the controller (which I don't really get), then you could build up modules that can be included there - that way you preserve the clean separation of business logic from the web app.

If either technique were to be used, then it would seem to me that you've achieved the goal of separating the business logic from the rest of the application, and the slightly tighter coupling between controller and view is an acceptable trade off.

Or are there some considerations that I'm completely unaware of?

Dave Thomas

Robert:

I agree--stick the business logic in the models. But then, in the controller, you're left with a very unDRY respond_to mess should you want to talk to multiple types of client. You also end up adding stuff to the application which isn't really application-level stuff (such as signon and session support, menuing, and so on).

Ron Phillips

I like the idea of putting all the pretty pages on their own server. It seems to be causing all kinds of grief to try to provide a bunch of alternative html pages at the REST level. I think that the REST service should provide the most generic possible html representation of a resource.

I thought it over, and I still think stylesheets might be useful for that one generic page that REST provides.

If someone's requesting html format representation, then they are either looking for a generic human-readable page, a generic human-editable page, or links to less-generic pages. So send them all, let the client sort them out.

There's a prototype at http://uber.engineer.co.summit.oh.us/demo/players/1/ Fiddle the "Set my role" links, and try turning styles off, too.

1. If the client already has a "role" cookie set -- in this example, it might be a "geo_editor" role -- then they get a slightly better-adapted page.
2. If they've turned off JS, or cookies, or stylesheets, then the page degrades gracefully and gives them everything.
3. If they really want a nice, slender, well-tuned page with geographic editor's tools all ready to go, then they can hit the link provided.

I like the idea of the REST service providing generic data with links to more well-tuned versions. However, stylesheets let the browser make the generic version a little better adapted to a human user, without multiplying sub-formats.

Ron

Ben Francis

If you want to use stylesheets as part of the solution, why not use XSL on the server rather than CSS on the client. Have the RESTful application return a generic XML representation (maybe DIAL [1]) and then use XSLT to create the representation requested in the user agent's Accept header based on the relevant XSL stylesheet. I believe this is called a transform view in the MVC pattern.

But this is straying off the original point.

1. http://www.w3.org/TR/dial/

Ron

Well, that would be slick -- I don't think it's really OT. The original post said:
.
.
.
If I want to fetch an article for viewing on a browser, I can use

GET /article/1

If, instead, I want to allow the user to edit the resource, I issue

GET /article/1;edit

The application then sends down a form pre-populated with the data from that article.
. . .
The ;xxx notation looks like it was tacked on.
.
.
.
Well, if we send both viewable and editable representations of the data, we don't need to sort out why the client wants the data. We don't have to tack on REST-breaking subformat stuff. Just send it all, and, as a courtesy, allow the browser some tools to tailor the look to the user.

Ron

Ron

Maybe I'm not understanding at all. Could someone please set me straight on the following?

I thought that:

1. The content is determined by the fact that the user requested a GET on that resource

2. That whole ";edit" thing was about presentation, which is a stylesheet's job.

3. The "/edit" option's not really RESTful, either -- the /'s are supposed to indicate subsets of the resource (like GET /articles/recent), not varying presentations of the same content

or didn't I understand?

Ben Francis

Ron wrote:
"If we send both viewable and editable representations of the data, we don't need to sort out why the client wants the data."

The reason I think that server-side transformations are off topic is that yes, we should send both viewable and editable representations, but they should be the same thing.

The URI should be the same, the Accept header should be the same (because it's still the same MIME type), but there should be something in the user interface that means if the user has permission, they should be able to edit the resource they have downloaded.

The challenge with this idea is that if the resource at the back end is anything other than a plain HTML document, some logic will be required to translate changes made to the HTML representation into changes in the underlying data model.

Server side transformations are more useful for translating a generic XML (e.g. DIAL) representation into other formats (e.g. SVG, X3D, VoiceXML...). This is true device independence.
http://www.tola.me.uk/concepts/2006/device_independent_web_server

lninyo

REST: is it about Representation or Representational State Transfer? IMO, emphasis is on the "state transfer" part.

jsled

@Ron: There's no requirement that there's only one representation of a resource that serves all (view, edit, print, ...) purposes. Also, there's no requirement that only one URI identifies any resource.

{/articles/#/editable}, then, maybe? Sub-resources can be logical ones, such as {./editable} and {./printable} ... they can be resources that are themselves representations of another resource. Think of {/articles/#/en} vs. {/articles/#/de} or {/images/foo.svg} vs. {/images/foo.png}. These can all be the results of content-negotiation on {/articles/#} or {/images/foo}.


@DaveThomas: your comment system eats both {less,greater}-than characters and
ampersand-{lt,gt}-semicolon sequences. :/

Dave says: I guess Typepad is trying to protect the world...

Pat Maddox

I'm a bit confused as to how the presentation server would be implemented. I understand how it'll communicate with the REST server of course...but how do users view and edit resources?

GET /articles/1
GET /articles/1;edit

I realize that splitting out a presentation server doesn't preclude it from using an outward-facing RESTful architecture as well...but in that case I'm not sure I see a compelling upside.

Tim Lynch

I understand that /articles can get me all the articles (or, say, all article summaries), and that /articles/1 would get me article 1. But, say I want some arbitrary subset of articles, say: [1, 7, 13, 253]? How would that request be represented? How about if I wanted the edit representation of each article in that subset?

jsled

@Tim Lynch: as 4 seperate requests ...

HTTP isn't a replacement for traditional RPC APIs. It makes different tradeoffs. For instance, there's no way to operate on more than one resource at a time, as you imply.

One could imagine POST /articles/group {1,7,13,253}, and getting some /articles/group/# back ... but that's some particular application semantic, not something defined by HTTP.

Mathias Biilmann

At Webpop.com ( http://webpop.com ) we're using exactly this kind of architecture for our upcomming suite of web-applications (though we are not using Rails for the business-logic containing REST-service so far). We're still using the respond_to stanzas quite a bit in the presentation applications to get the ajaxified parts of the apps to degrade gracefully. The 'RADAR' approach works very well for us so far, and it seems to me that by sticking the REST service in it's own application, we're able to split what would have been one kinda clunky application into various very clean smaller apps.

I wonder if you saw Mark Nottingham's presentation at Q-Con a few weeks ago? It seems Yahoo's architecture is based on the same pattern, with some heavy Squid based caching thrown in between the Dumb-Ass Recipients and the REST back-end application server. This seems to be really powerful for scaling purposes - especially considering how well Yahoo holds up to their 4 billion daily hits: http://royal.pingdom.com/?p=116

P.S.: Thanks for your great "Developing Expertise: Herding Racehorses, Racing Sheep" presentation at Q-Con! It was very inspiring.

Steve

Mathias,

If you don't mind my asking, what is the relationship between Dumb-Ass Recipients (DAR's) and REST back-end app servers (RA's) at webpop.com? One-to-one, one-to-many, many-to-many? Did Mark Nottingham say what the relationship between DAR's and RA's was in Yahoo's architecfture?

Thanks.

Steve

Jason

Hi
Firstly, I concur with many that I dislike mixing nouns and verbs in the URL.
The pattern, as I understand it, is to have a RESTful back-end (Rails) talking with a ActiveResource enabled front-end.
The back-end does not need to be concerned with representation, so the ActiveResource calls are all that is needed at that level. The back-end has the models and simple controllers, the front-end, more complex controllers and lots of views.
This leaves the interaction between the dumb client and the front-end, which now has to include communication about presentational logic. Have we just moved the problem, if we wish to keep the same clean noun-based URLs for the user?

The protocol I think I'd like to implement for the front-end looks something like this:

GET /articles ACTION => index
GET /article ACTION => new
POST /article ACTION => create
GET /article/# ACTION => edit/show (depends on authorisation)
PUT /article/# ACTION => update [using :method ]
DELETE /article/# ACTION => delete [ using :method ]

I've been using singular forms of resource URLs with the current resources routing, because, to me, I edit a singular resource not a group of resources.

Given that Rails uses such conventions elsewhere, why not use a similar convention in interpreting the URL. Avoids the use of those ugly verbs in the URL.

In the meantime, I think for the front-end I'll be writing a few map.connect commands to emulate this.

roberthahn

On the subject of designing URIs, I've spent a couple of days mulling it over, and would like to invite you guys to come check out my post at http://blog.roberthahn.ca/articles/2007/04/06/url-design

Lynch

@jsled: HTTP isn't a replacement for traditional RPC APIs.

right, I get that. Let me see if I can be more clear with my question. From all that's been said and written, there are many good reasons to adhere to a RESTful approach whenever possible. But, from my understanding, REST does in fact limit me to getting one thing at a time, or one pre-defined set or list of things. For example, the server end of an app might allow for /documents/1 and also might allow, say, /documents/1/abstract where the latter returns just the abstract of doc #1. The app could also define a target called "brief" which returned {title, author, abstract, conclusion}.

But, what if the app didn't define "brief" and that's what I needed? I'd have to make 4 GETs, right? One for each part {title, author, abstract, conclusion}.

Is it better to do the REST thing and make 4 GETs, or is it better to build a custom RPC? I ask that in all sincerity, for it seems to me that most applications will need, over time, the flexibility to GET custom sets of items or attributes. And, if I have to build that flexibility, when do I get to use REST?

Is there a more RESTful way to create a custom RPC? For example, would a good approach be to build the app to understand POSTs that create on-the-fly targets (for want of a better term):

POST /documents target={"brief": ['title', 'author', 'abstract', 'conclusion']}

followed by:

GET /documents/1/brief (assuming the server caches the definition of brief for some reasonable time period)

OK, my syntax is bollocks, but I think you get the point. Would that be considered RESTful?

jsled

@Tim Lynch: ...

REST optimizes for coarse-grained representation transfer; the balance of
that is the inefficiency of operating on the whole document, not the 4
specific parts you need ... in the common case.

If the system is regularly dealing in resources that are sets of others, then
that system should create those resource-collections as resources and traffic
in them.

Think about HTML ... it has no notion of documents or word-processing, yet
you can build Writely or blog editors or .... The key enabler there is a
widely-applicable data-representation with a forms language (HTML) (; I also
maintain that the fact HTML is orthogonal to any specific application domain
is critical, but ...) Your system might have more specific media-types that
aren't as widely accepted.

As for RESTfulness, the key still remains: traffic in the hypermedia
representations of identified resources, using a set of uniform operations.


FWIW, I would formulate a "custom RPC" as:

POST /dispatch
{op: "getDocumentParts", args: [{"id": "document/1"}, "title", "author", "abstract", "conclusion"]}

The form where it's more like:

POST /documents/1
{op: "getParts", args: ["title", "author", "abstract", "conclusion"]}

... is a gray area I think people wrestle with. It's still "RPCish", but
with a URI as an argument. I guess I'd argue that in as much as it's
server/forms-driven, it's closer to REST; we have POSTs that are really
"bookAirlineTicket" all the time, but they're RESTfully in HTML and forms.

But better still is the POST as you described, imho.

Eleanor McHugh

The rush to REST is one more case of premature optimisation. Yes it makes sense for HTTP traffic to comply with REST, but application developers should be thinking in terms of the verbs that are natural to their applications - not the artificially restricted set of HTTP verbs.

We no longer write our Desktop applications in assembly language because for all the potential performance benefits the time taken to develop significant applications in this manner is prohibitive. Likewise any semantically rich web application is better developed using a rich set of verbs (dare I say methods?) and then this should be translated to a RESTful implementation by software.

I like the idea of RADAR as in a sense it's proposing a very similar approach to this. The proxy knows all about REST and can consume resources efficiently over the network, but at the same time it allows a developer to build a rich application without those restrictions.

Unfortunately the traffic between browser and proxy is perforce unRESTful, but given that much of the internet current lacks any kind of reliable caching infrastructure I doubt that this would in practice make much difference.

In the longer term what's really needed though is a successor to HTTP with a less-restrictive verb model...

Lynch

jsled, eleanor, thanks for the thoughtful replies

re: In the longer term what's really needed though is a successor to HTTP with a less-restrictive verb model...

how about beep? www.beepcore.org

jsled

@Eleanor: There's nothing premature about it. Bear in mind that most of the REST constraints exist to enable caching ... much of the point of having a restricted and uniform set of methods is to enable the definition of the semantics of those methods for the benefit of intermediaries: proxies and caches. As for a the internets lacking a reliable caching infrastructure, you might want to ask any large website how much bandwidth they save when they correctly use conditional GET and cache control headers on responses... or take a look at Akamai.

I'm not saying that application developers shouldn't be thinking in terms of their application, or that a successor to HTTP with an expanded verb *set* wouldn't be useful. But is can be hard to balance and an expanded verb *model* with cacheability. I know HTTP-NG started down that road of specifying the cache behavior of operations independent of the operations themselves, but all it could really end up with was: "you can flag methods as cacheable (derived from GET) or not (derived from POST)". And, hell, most browsers and servers don't even implement most of HTTP 1.1, let alone WebDAV ... even more complexity is ... well ... is WS-*.

Another example of cacheability in protocols is IMAP (headers) ... and NNTP ... both cases with a defined set of protocol operations with explicit cache-control semantics defined.

Verify your Comment

Previewing your Comment

This is only a preview. Your comment has not yet been posted.

Working...
Your comment could not be posted. Error type:
Your comment has been posted. Post another comment

The letters and numbers you entered did not match the image. Please try again.

As a final step before posting your comment, enter the letters and numbers you see in the image below. This prevents automated programs from posting comments.

Having trouble reading this image? View an alternate.

Working...

Post a comment

Now in Beta

  • Programming Ruby, 3rd Edition
    Third Edition, Covering Ruby 1.9, now available
My Photo

Pragmatic Stuff

Photos

  • www.flickr.com
    This is a Flickr badge showing public photos from pragdave tagged with pragdave_badge. Make your own badge here.

Site Search

  • Google Search

    The web
    PragDave