0

I'm designing RESTful resources for accessing media. Media could be a live stream or archived stream. I'm using O'Riellys text "RESTful Web Services' as a guide but I'm struggling with the representation of resources relative to the 'programmagable web' versus the 'human web'. For human web request I'd like to return an HTML representation. For programmable web requests I'd like to return XML. That being said, consider:

GET http:// localhost :8080/stream - returns a list of streams

GET http:// localhost :8080/search?stream=abc - return a specific stream

How do I differentiate between a request from the 'human web' versus the 'programmable web' such that I could return the right representation?

O'Reillys text seem to suggest design of two seperate resources. From page 24 of the PDF he states:

I’d use the same tools to fetch and process a web page. These two URIs: 1) http:// api. search.yahoo.com/WebSearchService/V1/webSearch?appid=restbook&query=jellyfish 2) http:// search.yahoo.com/search?p=jellyfish point to different forms of the same thing: “a list of search results for the query ‘jellyfish.’” One URI serves HTML and is intended for use by web browsers; the other serves XML and is intended for use by automated clients.

Are two separate resources for dealing with the human web versus programmable web the norm or is there alternatives? Thoughts welcomed.

laurent
  • 88,262
  • 77
  • 290
  • 428
ma740988
  • 11
  • 3

2 Answers2

0

I'd say the official "fielding compliant" answer is to use content type negotiation using the ACCEPTS header. Lots of good stuff at http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm

If the client requests text/html, feed the human readable html. If the client requests text/xml, feed it xml. The trick here is that pragmatically this isn't always well supported by the clients, so you'll often need a bunch of fallbacks using query strings or resource name mangling, as in the example you posted.

Personally, I try to follow ideology as long as I can, and then start adding fallbacks pragramaticly as necessary. I wouldn't create a separate resource for programmatic or human consumption until you run into a client that can't properly handle sending an accept header.

easel
  • 3,982
  • 26
  • 28
0

Your example doesn't match the question, so I will answer both.

In the example you give, you have two different resources: a list of streams, and an individual stream. As such they should be allocated separate URIs, and I would strongly recommend against using the query string for that where there is a clean and obvious alternative.

In this case it is classic ReST. /stream/ is the Resource consisting of the list of available streams, this list should be presented as a either a human or computer (or preferably both) list of URIs so (as text/html):

<ul>
  <li><a href="/stream/abc">ABC</a></li>
  ...
</ul>

This leads to your next question, how to identify the different Representations of the stream-list Resource. There are three techniques I have used: content negotiation, format query param, and RDFa.

RDFa is my preferred alternative, in this case you only have one representation that encodes both human and machine readable content. In the case of a simple list this is a trivial change to your HTML:

<ul>
  <li><a rev="rdfs:member" href="/stream/abc">ABC</a></li>
  ...
</ul>

If you have one or more pure machine serializations of your data then there are two alternatives I have used; generally, both at the same time.

Content negotiation is the purest, and most convenient. Just have one text/html, and another application/xml or application/json, and let the client choose.

This isn't as convenient when testing the machine version from a browser, command line (curl/wget/etc), or a script. So I like to also support a format query parameter. For convenience sake, have it take a mime-type.

I prefer to have my resource handled by the same controller/servlet/etc, have it fetch the information from the filesystem/database/whatever, and dispatch it to the appropriate view based on the mime-type (content neg or format param) for display. Either way you are dealing with different representations of the same resource, so it is a good idea to ensure they are available from the same Base URI, whatever alternative approaches you decide to support.

Recurse
  • 3,557
  • 1
  • 23
  • 36
  • ;So I like to also support a format query parameter. For convenience sake, have it take a mime-type' – ma740988 Jun 03 '12 at 19:04
  • 'So I like to also support a format query parameter. For convenience sake, have it take a mime-type'. Could you provide an example of a URI that takes a mime-type predicated upon the base uri? You could use the URIs in my initial post as a base. – ma740988 Jun 03 '12 at 19:22
  • Sure. Entering http://localhost:8080/stream into a browser would return the HTML, human-readable, version. As would http://localhost:8080/stream?format=text/html. Alternatively http://localhost:8080/stream from a process that sets the ACCEPTS header to application/xml would return the same content as machine-readable xml. However if you support a format query param, you could also enter http://localhost:8080/stream?format=application/xml into a browser and receive the xml version there. I find this invaluable for debugging. – Recurse Jun 07 '12 at 06:40