[Rails] Rest and Mime Types

Eric Anderson eric at afaik.us
Mon Jul 31 01:14:20 GMT 2006


Been thinking about something lately and wanted to hear what others 
thought. After watching the video[1] of DHH with the slides[2] I really 
liked some of the ideas presented. Many people have noted the ugliness 
of needing secondary actions since HTTP actions do not cover the full 
range of CRUDness (i.e. the "GET /people;new" and "GET /people/1;edit"). 
Also the need for occasional actions that fall outside the standard CRUD 
("POST /people/1;closed").

Some people are just disturbed by the URL. That doesn't bother me. What 
bothers me is that conceptually we have two actions associated with the 
request which just seems awkward. On the flip side since HTTP doesn't 
support arbitrary actions it seems we just have to live with this 
awkwardness.

BUT, the other concept presented (using Accept headers, extensions and 
mime types to determine what is returned) seemed to me to be the answer 
to this awkwardness. The idea presented was to use the "Accept" header 
(or as a fallback an filename extension) to determine what the user 
wants. So:

GET /people/1
Accept: text/html

returns a HTML page of the person requested while:

GET /people/1
Accept: text/xml

returns a XML representation of that person. My question is what is the 
difference between that and doing something like:

GET /people/1
Accept: application/x-edit

instead of

GET /people/1;edit

When we do:

GET /people/1
Accept: text/xml

we are saying "Give me the person with id '1' in XML format". When we do:

GET /people/1
Accept: application/x-edit

we are saying "Give me the person with id '1' in a editable format (HTML 
form)". The same would apply to "new". So:

GET /people
Accept: text/xml

says "Give me people in XML format". While

GET /people
Accept: application/x-new

says "Give me people in a format that I can create a new person".

One more example.

POST /people/1
Accept: text/html

This says "Save person with id '1' in a manner accepts HTML forms" while:

POST /people/1
Accept: application/x-closed

says "Save person with id '1' in a mannor that closes it"

We could even use the file extension trick since sending Accept headers 
can sometimes be difficult. So we might have:

GET /people.new
GET /people/1.edit
POST /people/1.closed

Of course all of this would map to the same actions in your controllers 
as they do now. In the end all that is really changing is that we are 
changing a ";" to a ".". But conceptually we are transforming an request 
with two actions into a request with one action but with different 
formats requested. In my mind this provides a constancy since we are 
already doing this when requesting XML, JS, mobile-content, etc.

I am curious what others think? Is this all crazy? Am I overloading 
mime-types way to much? Traditionally we have considered the following:

GET /people/feed

as saying "Carry out the action 'feed' on the list of people. This 
action returns RSS content." Now we do this:

GET /people
Accept: application/rss+xml

as now saying "Give me a list of people in RSS format". We have moved 
from specifying an action to specifying a format. My question is why 
can't we do this for all cases. So while right now we say:

GET /people/1;edit

which means "Give me person with id '1' and carry out the secondary 
actions of 'edit'" we might be able to say:

GET /people/1.edit

which says "Give me person with id '1' in a format that I can use to 
edit that person".

I am interested to hear what others things.

Eric

[1] 
http://blog.scribestudio.com/articles/2006/07/09/david-heinemeier-hansson-railsconf-2006-keynote-address
[2] http://www.loudthinking.com/lt-files/worldofresources.pdf



More information about the Rails mailing list