views:

56

answers:

4

I have a representation that contains a list of items. This could easily contain several hundred items.

<List>
  <ListItem>...</ListItem>
  <ListItem>...</ListItem>
...
  <ListItem>...</ListItem>
  <ListItem>...</ListItem>
</List>

For each item I want to provide a set of links that are available. Of the set of links, each item may only be allowed to access a subset of those links depending on some condition.

The following example demonstrates a brute force way of doing it.

<List>
  <ListItem Id="345">
     <Link rel="foo" href="http://example.org/List/Items/345/foo"/&gt;
     <Link rel="bar" href="http://example.org/List/Items/345/bar"/&gt;
  </ListItem>
  <ListItem Id="346">
     <Link rel="bar" href="http://example.org/List/Items/346/bar"/&gt;
  </ListItem>
  <ListItem Id="347">
     <Link rel="foo" href="http://example.org/List/Items/347/foo"/&gt;
  </ListItem>

 ...
</List>

Here is an alternative way

<List>
  <ListItem Id="345" AvailableRels="foo bar"/>
  <ListItem Id="346" AvailableRels="foo"/>
  <ListItem Id="347" AvailableRels="bar"/>
 ...
  <Link rel="foo" href="http://example.org/List/Items/{Id}/foo"/&gt;
  <Link rel="bar" href="http://example.org/List/Items/{Id}/bar"/&gt;
</List>

The second approach looks much cleaner, it requires more intelligence on the client to deal with the URI template. The second is obviously much smaller to transfer over the wire, however, I am doing HTTP compression, so should I really care?

Thoughts? Are there other issues that I am missing? Is the AvailableRels idea a bit too non-standard? Is there anything like that in other media types?

+1  A: 

If you're simply looking to reduce the size, consider including a 'self' link to the representation as a whole (which must be absolute), and declaring that all relative links are relative to it in your media type or protocol spec. (This is how Shoji does it) Then your example shrinks to:

<Link rel="self" href="http://example.org/List/Items/"/&gt;
<List>
  <ListItem Id="345">
     <Link rel="foo" href="345/foo"/>
     <Link rel="bar" href="345/bar"/>
  </ListItem>
  <ListItem Id="346">
     <Link rel="bar" href="346/bar"/>
  </ListItem>
  <ListItem Id="347">
     <Link rel="foo" href="347/foo"/>
  </ListItem>

 ...
</List>
fumanchu
Hmmm, not sure why I didn't think of that. I actually include an xml:base in most of my representations for just that purpose. Thanks.
Darrel Miller
I would even go as far as to just use relative URIs. It's one of the few complexities that belong on the client... But remember that REST is a tradeoff, and one of the big tradeoffs is efficiency.
mogsie
You can certainly use URI's which are relative to the document in all the ways specified by the RFC's. Including a "self" link allows one to persist the document through all sorts of filesystems and other storage systems which might not necessarily keep the HTTP metadata around with it.
fumanchu
+1  A: 

Both of these are in some new media type, so I guess that you get to define the processing models for both of these. The natural instinct is to go with the first one, since it doesn't add the invisible coupling between an attribute in one area of the XML and a URI template in some other place.

Prior art to guide us would be e.g. atompub or sun cloud API, both of which expose an enormous number of links, often repeating. I's just want to point out that OpenSearch could be handed as evidence for the URI template approach, since it exposes URI templates and special <Url> and <Query> elements that have element names matching the braces of the URI template. I personally consider OpenSearch templates very RESTful. Also plain HTML forms do something of the same, and can't not be considered RESTful in their base form.

The downside of providing URI templates is that you can't easily partition half of your items to have a href that goes to server A, and another that goes to server B, or that the different halves actually have different places. You're actually leaking something about the underlying data structure to your clients, and the clients therefore become dependent on all items having the same(ish) URI scheme for accessing foo or bar, making it all less flexible (perhaps depending on how you document the media type in question).

mogsie
Excellent points, thanks.
Darrel Miller
A: 

What about just introducing pagination, if you're worried about raw resource size?

<List>
  <Previous href="http://example.org/List/before/345"/&gt;
  <Next href="http://example.org/List/after/987"/&gt;
  <ListItem Id="345">
     <Link rel="foo" href="http://example.org/List/Items/345/foo"/&gt;
     <Link rel="bar" href="http://example.org/List/Items/345/bar"/&gt;
  </ListItem>
  ...
  <ListItem Id="987"> ... </ListItem>
<List>
mogsie
A: 

Looking at your representation I am finding very striking resemblance to Atom Syndication Format, which does this using atom:entry and atom:link. To be honest I am at an awe with Atom Syndication Format (ASF).

The RFC for ASF http://tools.ietf.org/html/rfc4287

The pagination of entries within ASF - rfc5005

If the RFCs are used your feed would look like -

   <?xml version="1.0" encoding="utf-8"?>
   <feed xmlns="http://www.w3.org/2005/Atom"&gt;
     <title>Example Feed</title>
     <link href="http://example.org/" rel="self" />
     <link href="http://example.org/before/345" rel="next" type="application/atom+xml" />
     <link href="http://example.org/after/987" rel="previous" type="application/atom+xml"/>
     <updated>2003-12-13T18:30:02Z</updated>
     <author>
       <name>Darrel Miller</name>
     </author>
     <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>

     <entry>
       <title>Item 987</title>
       <link href="http://example.org/List/Items/987/foo" rel="foo" />
       <link href="http://example.org/List/Items/987/bar" rel="bar" />
       <id>987</id>
       <updated>2003-12-13T18:30:02Z</updated>
       <summary>Some text.</summary>
     </entry>
     ...
     <entry>
       <title>Item 345</title>
       <link href="http://example.org/List/Items/345/foo" rel="foo" />
       <id>345</id>
       <updated>2003-12-13T18:30:02Z</updated>
       <summary>Some text.</summary>
     </entry>

   </feed>

I suggest using this as would give power to the client to leverage standard clients to consume your representation. I personally prefer pagination in accordance with what mogsie mentioned above with ASF. Once pagination is in place I would suggest the standard HTTP stuff to improve performance:

  • Set HTTP Cache related headers in the response so that clients can use them to cache responses
  • Use a Cache server (Squid, Varnish) in front of the Application Server to reduce generating feed everytime.
  • Support compression, i.e., support both plain and compressed content depending on client capabilities.
imyousuf