Darrel Miller
Darrel Miller

Reputation: 142222

How to create a hypermedia list with item sensitive links?

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"/>
     <Link rel="bar" href="http://example.org/List/Items/345/bar"/>
  </ListItem>
  <ListItem Id="346">
     <Link rel="bar" href="http://example.org/List/Items/346/bar"/>
  </ListItem>
  <ListItem Id="347">
     <Link rel="foo" href="http://example.org/List/Items/347/foo"/>
  </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"/>
  <Link rel="bar" href="http://example.org/List/Items/{Id}/bar"/>
</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?

Upvotes: 1

Views: 592

Answers (4)

imyousuf
imyousuf

Reputation: 1245

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 https://www.rfc-editor.org/rfc/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">
     <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.

Upvotes: 1

mogsie
mogsie

Reputation: 4156

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

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

Upvotes: 0

mogsie
mogsie

Reputation: 4156

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).

Upvotes: 2

fumanchu
fumanchu

Reputation: 14559

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/"/>
<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>

Upvotes: 2

Related Questions