Blog

RESTful URIs

2008-03-03 11:17:29 by Martynas Jusevičius

The RESTful Web Services book provides three basic rules for URI design, born of collective experience:

  1. Use path variables to encode hierarchy: /parent/child
  2. Put punctuation characters in path variables to avoid implying hierarchy where none exists: /parent/child1;child2
  3. Use query variables to imply inputs into an algorithm, for example: /search?q=jellyfish&start=20

We have come up with very much the same principles in our designs. The second rule however seems to be rarely used in practice.

The rules are tested and precise enough, but it is the definitions used in them that are not always clear. What constitutes a hierarchy? A strict class/subclass/instance tree is probably the most logical and intuitive form of it, for example Places/Clubs/VEGA. It should be used whenever it applies, but that is not always the case. Another good example is things that are embedded one into another, such as Countries/USA/Georgia/Atlanta.

Many hierarchical paths however break these two patterns, or mix them. For example, Places/Clubs/VEGA/Pictures/ or user/john/tags/ do not represent a strict hierarchy. Pictures/ is neither an instance of Places/Clubs/VEGA/ nor embedded in it in a strict sence. Still it is a kind of resource that should be given a RESTful URI.

Imagine that we would like to add pictures for every location in our location hierarchy. The pictures of USA would then be addressed as Countries/USA/Pictures/. This breaks our URI “embeddedness” hierarchy by adding some “metadata leaf nodes”, which are not true nodes (locations). When handling such a request most Web applications (especially those based on URL rewriting) would not be able to easily tell that Pictures/ does not refer to one of the US states as Georgia/ does. Last.fm for example distinguishes between these two kind of URIs by using a + prefix: music/Radiohead/In+Rainbows (album) vs. music/Radiohead/+events. Using the DIY Framework that is not necessary, since each resource has an explicit type which does not depend on its URI.

Another example found in practice is path URIs used for pagination, e. g. user/john/tags/all or /posts/4/pages/2. Again, they break the strict hierarchy, but also lead to the definition of algorithm in the 3rd rule. In our eyes, pagination is much more an algorithm than a kind of hierarchy. One can argue philosophically about resources and how best to design them, but we see a list of posts as a single resource which representation can be paginated used query parameters passed to an algorithm rather than a number of resources for every page. It can also have more inputs than the page number, e. g. the number of posts per page or the sort order, which would be hard to embed in the path. Therefore we use pagination URIs like Products/?offset=1200&limit=20.

The bottom line is that the URI space is infinite, but in practice the design choices for logical RESTful URIs are often difficult and constrained.

Digg Digg this! del.icio.us del.icio.us!

Comments (10)

2008-03-03 13:03:24 by Piccolo Principe

I wonder how much is search engine friendly Products/?offset=1200&limit=20...

Piccolo,

2008-03-03 13:08:55 by Martynas

I just checked on Google, and it does not seem to have problems to index URIs like this:
Products/?lang=lt&offset=1360&limit=20&order-by=Product.CODE

2008-03-03 16:23:54 by Oliver

It doesn't have a problem, but prefers 'static' url's since it correlates more often than not to 'original 'content, where as query paramaters are ofted associated with db related data, that may not be original in content (like page listings, print pages, etc.)

I'm reading that book right now, just finished Ch. 4. I'm liking it so far.

2008-03-03 22:51:10 by troels

"""
Using the DIY Framework that is not necessary, since each resource has an explicit type which does not depent on its URI.
"""

Could you expand on that?

troels,

2008-03-04 13:00:52 by Martynas

A Resource is simply a class, which has an URI and doGet() doPost() etc methods. You can subclass it, and the type does not have anything to do with the URI. During the request, controller maps resource URIs to their types and dispatches to the right class.

For example, I can create a CityResource with an URI <Countries/Denmark/Copenhagen/> and PictureListResource with an URI <Countries/Denmark/Pictures/>. If the first URI is requested, CityResouce class is executed, if the second one, PictureListResource is executed. There is no ambiguity even though both URIs follow the same pattern.

2008-06-12 04:44:33 by joel

I like to use the colon for non-hierarchical associations.

/search:foo would search for the term "foo" across all resources.

/US/search:bar search can be thought of a special sub of US. in this case it would search for all resources containing the term "bar" within the US (ie. ignore /Canada/ for example).

For paging I use /US/State/City/page:2 or /US/search:term/page:2. In that sense I do consider page to be a sub of their parent. If you draw a tree you can make place "page:1", "page:2" etc.. as leaves, which seems to fit well. The numbers aren't a sub of page, just an argument of.

So for pictures I would do something like /US/picture:23.jpg rather than /US/pictures/23.jpg. The image isn't a child of pictures. It is a picture. It would be a child of an album though, and in this case the album is "US".

To be more explicit you can do something like:
/album:US/picture:23.jpg to show picture # 23 in the US album.

ODKpLpLOcOsS

2009-05-16 20:49:46 by ebnzddk

lIxa9A <a href="http://pnvhjyfezruy.com/">pnvhjyfezruy</a>, [url=http://khjgwusmhxku.com/]khjgwusmhxku[/url], [link=http://ylhqevoyhgrz.com/]ylhqevoyhgrz[/link], http://xdezpqklshol.com/

SmlPnrjczwDmOipSDxT

2009-06-19 01:52:08 by bkztgzkw

PWegmW <a href="http://ljugqkpexqde.com/">ljugqkpexqde</a>, [url=http://muxafchrrtdn.com/]muxafchrrtdn[/url], [link=http://ipvgwcnlscqz.com/]ipvgwcnlscqz[/link], http://mgeababmghce.com/

ugg boots

2010-08-23 05:29:56 by ugg boots

i like<a href="http://www.buyuggsite.com ">ugg boots</a>,<a href="http://www.buyuggsite.com/ugg-argyle-knit-5879-boots-c-14.html ">uggs</a>,<a href="http://www.buyuggsite.com ">ugg australia</a>,<a href="http://www.buyuggsite.com ">ugg classic</a>,<a href="http://www.buyuggsite.com/ugg-argyle-knit-5879-boots-c-14.html ">ugg boots uk</a>,especlially like<a href="http://www.buyuggsite.com ">ugg classic tall</a><a href="http://www.buyuggsite.com/ugg-bailey-button-5803-boots-c-35.html ">tall ugg boots</a><a href="http://www.buyuggsite.com/ugg-bailey-button-5803-boots-c-35.html ">short ugg boots</a><a href="http://www.buyuggsite.com/ugg-classic-cardy-5819-boots-c-8.html ">uggs sale</a><a href="http://www.buyuggsite.com ">buy ugg</a><a href="http://www.buyuggsite.com/ugg-classic-cardy-5819-boots-c-8.html ">buy ugg boots</a><a href="http://www.buyuggsite.com/ugg-classic-crochet-5833-boots-c-1.html ">discount ugg</a><a href="http://www.buyuggsite.com/ugg-classic-crochet-5833-boots-c-1.html ">buy uggs</a><a href="http://www.buyuggsite.com/ugg-classic-mini-5854-boots-c-10.html ">ugg boots online</a><a href="http://www.buyuggsite.com/ugg-classic-mini-5854-boots-c-10.html ">discount uggs</a><a href="http://www.buyuggsite.com/ugg-classic-short-5825-boots-c-9.html ">buy cheap ugg boots</a>

Bvlgari Jewelry

2010-08-28 09:48:38 by Bvlgari Jewelry

good

New comment






No HTML allowed.