Taking a REST

Most of my work is in rails, which promotes a particular vision (some would say particularly wrong) of REST. When we speak of REST, it is mostly because we want to have a set of endpoints with well-defined operations, where each operation acts on a single resource. These days, we have three goals:

  1. Make a set of web pages that give a reasonable experience in the absence of javascript, which all have nice URLs
  2. Have the same set of pages work really bloomin’ nicely with javascript turned on
  3. Present a set of urls that represent resources and define actions on those resources.

We had a very spirited discussion about this at work yesterday, in which I declared that you can’t meet all 3 goals. Here’s why.

When using javascript to make pages really slick, there’s a set of url endpoints that you want, a la goal 3. Some of those endpoints will be identical with the urls you want your nice user-facing web app to have for goal 1. The first goal requires some properties, and the second demands others. Eventually, conflicts between them will force compromise, and then what it means to be a resource will be ambiguous, and then? Bugs! Bugs, glorious bugs.

What’s the solution? It could be to add a layer; your pure domain sits underneath the shiny js pages, which interact with it directly, and also underneath the non-js site, which aggregate it into noice pages. But might it be possible to twist it around, instead? When you access a UI endpoint, it issues you with a handful of resources, and each resource has it’s own url but is also accessible via the UI endpoint. The framework talks of what it means to update a resource in a particular context, and so can offer both endpoints without developer intervention.

Does that exist yet? Anyone tried to build something like it and able to tell me why it can’t be done?

2 thoughts on “Taking a REST

  1. I don’t quite follow all of this, but I do get what you mean by the three goals. What is the compromise you speak of? Is it between goals #1 and #3, or #1 and #2?

    What is wrong with simply having #1 be a set of nice URLs which return web pages nicely formatted for the user, and having #3 be a completely disjoint set of nice URLs which form an API that returns and receives machine-readable (i.e., JSON) data? #2 is just an additional view over the same URLs as #1, only it dynamically updates the page by talking to #3.

    I suppose this introduces a kind of “ambiguity”: your HTML URLs (#1) and JSON URLs (#3) represent the same resources. But with different purposes. I like to think of them as 1:1 corresponding human and machine-readable (respectively) resources. So have the URL scheme mirror. Have /mgiuca/posts/7 return a human-readable HTML page, and have /api/mgiuca/posts/7 return a JSON representation of the same URL. Or alternatively, have the JSON view use the same URL with an argument: /mgiuca/posts/7?view=json.

    Then you have all three: a nice URL scheme with human-readable pages that do not require JavaScript, a JavaScript layer that makes it very sexy, and a slick API also with nice URLs. Did I completely miss the problem?

  2. You didn’t miss the problem at all, you very sensibly dodged it. If you introduce a separate /api namespace, then you’re all happy times. The only thing wrong with it is that, with all the current technologies I’m aware of, if you want to do anything to stuff as it comes in (enforce access control, force validation, force defaults), you have to do it for both / and /api.

    The compromise comes when you assume that you can jam them all into the same namespace. What seems to happen in practice is that eventually the plain-old-html rendition requires that the input be delivered in some particular form, while the api rendition is more natural in another form.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s