Mixing data and interface in RESTful app

52 views
Skip to first unread message

Vlad K.

unread,
May 7, 2012, 9:24:10 AM5/7/12
to pylons-...@googlegroups.com

Hi all.


I am building an application that will be used both by humans and
machines ("via an API") and I am making it RESTful. I've decided to
design it as one big API where human-operated browser is just another
client to the API. With that I'm actually mixing user interface and data
in requests for certain resources.

For example, a list of profiles sits behind the /profiles URI.

If requested format is HTML (default), the the list of profiles is
returned as full HTML page complete with navigation links, sidebar
content, etc... It's a classic interface webpage.
If requested format is JSON (via Accept header, or ?format=json query),
only the data is returned as JSON array of profile dictionaries

The most obvious benefit here is that for each resource I basically have
single view handler (with the exception that POST/PUT and DELETE call
respective functions after the resource view handler has "prepared" the
resource in a way that's common to all verbs), and what is returned back
to client is only a matter of Renderer and template. The HTML renderer
uses templates that "know" how to include this additional data (nav
links, sidebar content, etc...)

So I have a single set of resources and only the requested format
defines whether the entire interface is sent back along with data for
humans and their puny browsers. Machines of course do not need all that
and talk in simple and effective JSON, but basically I have just one set
of view handlers.


However, I'm having a philosophical discussion with myself here whether
this is "truly" RESTful and whether I'll hit some kid of unforeseen
obstacle later.


Because the only alternative is separating "interfaces" (complete HTML
pages with navigation, sidebar content, blah) as different resources
which may or may not contain the data (ie. is it already present in the
page or must be requested with some background javascript magick against
the "real API"). While this does provide a cleaner separation of
concerns, I'm forced to have more view handlers for basically the same
thing because interface and its data are interconnected, there's no
generic interface here that can operate on different data, etc...

Or perhaps I can separate the URIs and have the interface view handlers
be just dummy functions that delegate to the actual API view handlers.



Opinions? Suggestions?


--

.oO V Oo.

Jonathan Vanasco

unread,
May 7, 2012, 11:44:51 AM5/7/12
to pylons-discuss
i generally hate this approach to web programming.

i find it very shortsighted and unmanageable for those you're trying
to service - if you change your website, the API more often than not
causes apps to break. i see this popular in the rails community where
not many projects last long.

if you're making something for machines, i'd suggest creating a
versioned API. if you're up go /v3/function, old clients can still
hit /v1/function and not break.

in terms of structure, you could cut this a number of ways
- use matchdicts and multiple view_configs to have everything operate
on a single handler/function , and change the output within the
function
- use multiple urls/handlers that all call an internal API/Library
function.
- a lot of other options

Bill Seitz

unread,
May 7, 2012, 12:01:26 PM5/7/12
to pylons-...@googlegroups.com
I agree, the human-UI needs to be optimized for an elegant UX, the API needs to be kept logically simple.

For the API, you should be able to automate a lot of the CRUD renderings by introspection on your db structure, equivalent to how Rails/Django auto-generate an admin interface.

For more details, I suggest you read RESTful Web Services. http://webseitz.fluxent.com/wiki/RestfulWebServices


--
You received this message because you are subscribed to the Google Groups "pylons-discuss" group.
To post to this group, send email to pylons-...@googlegroups.com.
To unsubscribe from this group, send email to pylons-discus...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.


Mike Orr

unread,
May 7, 2012, 2:59:51 PM5/7/12
to pylons-...@googlegroups.com
On Mon, May 7, 2012 at 8:44 AM, Jonathan Vanasco <jona...@findmeon.com> wrote:
> i generally hate this approach to web programming.
>
> i find it very shortsighted and unmanageable for those you're trying
> to service - if you change your website, the API more often than not
> causes apps to break.

I wouldn't go as far as saying I "hate" this approach, but the fact
remains that the interactive UI will inevitably require features that
the web-service API doesn't, such as additional data variables for
presentation features, or paging through the results. For the case of
extra variables (undesired in JSON), you can set them as instance
variables in the view (available in templates as 'view.*').

Routes has a feature where if you append a suffix to a Resource URL
(as in ".xml" or ".json"), the suffix would be passed to the action
via the 'format' routing variable. This may have followed a Rails/Atom
precedent. But whenever I tried to use it, I found that there were so
many other differences in generating HTML vs generating XML or JSON
that it was better to have separate actions for them. Also, it's not
very common to provide multiple formats for every URL, so many times
there was just no valid XML format I was willing to generate.

--
Mike Orr <slugg...@gmail.com>

Vlad K.

unread,
May 7, 2012, 6:15:56 PM5/7/12
to pylons-...@googlegroups.com

On 05/07/2012 06:01 PM, Bill Seitz wrote:
> I agree, the human-UI needs to be optimized for an elegant UX, the API
> needs to be kept logically simple.
>
> For the API, you should be able to automate a lot of the CRUD
> renderings by introspection on your db structure, equivalent to how
> Rails/Django auto-generate an admin interface.
>
> For more details, I suggest you read RESTful Web Services.
> http://webseitz.fluxent.com/wiki/RestfulWebServices
>

What you say about elegance is true, but this should be a RESTful
system. Meaning, we're dealing with resources, not action URLs. An edit
page interface is just resource data wrapped in stylized form HTML.
Basically HATEOAS on steroids, so to speak. So there is no API in a
strict sense, just resources. A machine does not need stylesheets,
menus, sidebar content, so the machine uses plain JSON format. Human
might prefer fancy HTML format of teh same data, and more.



.oO V Oo.


Jonathan Vanasco

unread,
May 7, 2012, 6:36:18 PM5/7/12
to pylons-discuss
My point is that the "machine" version will need to be pegged to
certain API versions - where consumers can expect to see certain
data, and hope to see other data.

The human version can constantly evolve, but the machine version needs
to be static and documented.

Vlad K.

unread,
May 7, 2012, 6:44:16 PM5/7/12
to pylons-...@googlegroups.com

You make a very valid point there, yes. I wasn't fully thinking about
it, and it's one of those things that have to be considered up front.

.oO V Oo.

Jasper

unread,
May 8, 2012, 3:07:01 AM5/8/12
to pylons-discuss
I don't think its short-sighted, in fact I use this approach, and it
fits very nicely with traversal.

Having a static versioned API is not a necessity. You only break the
(RESTful) API when you remove members from your resources. If you plan
to do this you can always warn your clients in time. Big APIs on the
web also change regularly, this is what (continuous) integration
testing is for. This is all assuming you have consumers that you do
not have a direct relationship with yourself. If you manage them
yourself it is not even a necessary to delay your upgrade.
Reply all
Reply to author
Forward
0 new messages