In order for your system to be RESTful, one of the the requirements is that the client doesn t know up front anything about how your URIs are structured. This means that you can t write code which builds URIs in a particular way like most twitter clients do. The conventional wisdom is that in order for a resource to be located, you need to discover its URI in a different place.
However, there are times that you re dealing a countless number of resources in the system, and providing links to each one is just plain stupid. Multidimensional data fits in this category. In these cases, it s completely valid to provide the client with rules for URI construction, as long as these rules are discovered at run time.
OpenSearch is absolutely a RESTful solution to this problem, and it s programmer friendly at that. A lot of the use of OpenSearch is limited to plain human readable HTML search results, but in actuality it can be used for purely machine readable (e.g. atom) search results too:
<Url type="application/atom+xml"
template="...search/?q={searchTerms}"/>
This template instructs clients that if you d like an atom representation, you can go here. But how does this fit multidimensional data? The extensibility of OpenSearch comes into play here. The OpenSearch time extension describes how to instruct clients to construct URLs that represent searches that are constrained to a specific time range (assuming xmlns:time
is bound correctly:
<Url type="application/atom+xml"
template="...search/?after={time:start}&before={time:end}"/>
If a client sees this template, it can see from the template that it only allows a time constraint. Let s extend it ourselves.
To extend OpenSearch, I have to designate a namespace and some elements in that namespace to mean something specific. This should be published somewhere so that others can access the documentation and implement their own servers and clients. Let s say you want to look a customer up by last name; last name is a pretty generic term, but not universal enough that it s been standardized. Let s say I define a namespace, bind it to the name
prefix in my OpenSearch description, and expose the following template:
<Url type="application/atom+xml"
template="...search?lastName={name:last}"/>
This template instructs any client that understands my name
namespace that it can do last-name lookups by filling out the template.
This still isn t multidimensional, but let s add another dimension; geography. Luckily, there s an OpenSearch draft extension for geography which allows searching within a bounding box or a circle:
<Url type="application/atom+xml"
template="...search/?latitude={geo:lat?}&
longitude={geo:lon?}&
metres={geo:radius?}"/>
I m splitting the template to make it readable.
The template still isn t multidimensional, since it only allows searching within one dimension (geospacial). So how do you do multidimensional searches? You provide a template which shows how to do multidimensional searches, that make sense to combine:
E.g. here s a template tha allows me to find people with a given last name in a different region (two dimensions):
<Url type="application/atom+xml"
template="combo-find?customerLastName={name:last}&
lat={geo:lat?}&
lon={geo:lon?}&
radius={geo:radius?}"/>
Here s a template that allows me to constrain names, and geospatial, along with a time constraint (although the OpenSearch Time extension doesn t say anything about what time you re looking for):
<Url type="application/atom+xml"
template="...search/?lastName={name:last}&
lat={geo:lat?}&
lon={geo:lon?}&
r={geo:radius?}&
after={time:start}&
before={time:end}"/>
In these examples, the client is free to look into the URI template to figure out what URI template parameters are to be filled out. So the client will know what dimensions each URI template supports, and can figure out which URI fits best at any one time.
The RESTfulness of all of this is because all of the REST constraints are honored; it s stateless, hypermedia is the engine, it s layered, etc. OpenSearch is just another hypermedia format, a very good one at that!