There has been some activity lately on trying to describe REST web services.
I don't mean explain, people seem to be getting the REST message... but to
describe them so that software can understand how to use them. I saw
this piece
during early april. The idea is to replace the SOAP-centric WSDL with a
REST-centric language. Essentially it describes how to take a number of
parameters and construct a URI from them. Here is their example:
<bookmark-service xmlns="http://example.com/documentation/service">
<recent>https://example.com/{user}/bookmarks/"</recent>
<all>https://example.com/{user}/bookmarks/all"</all>
<by-tag>https://example.com/{user}/bookmarks/tags/{tag}/"</by-tag>
<by-date>https://example.com/{user}/bookmarks/date/{Y}/{M}/"</by-date>
<tags>https://example.com/{user}/config/"</tags>
</bookmark-service>
Frankly, I don't agree. I've had some time to think about this, and I am now
prepared to call it "damn foolish". This is not the way URIs are supposed to
be handled. Note the by-date URI, which has an infinite number of possible
combinations (of which some finite number will be legal, for the pedants).
Look at the implicit knowledge required of which user parameters and which
tag parameters are legal to use. It's rubbish.
There are two things you need to do to make things right. First off, there
is a part
of the URI which is intended to be constructed by the user agent rather than
the server. This part is unremarkably called the query part, and exists after
any question mark and before any fragment part of a URI reference. I consider
this part to be the only appropriate space for creating URIs that are subject
to possibly infinite variation. The {Y} (year) and {M} (month) parameters must
follow a question-mark, as must {tag}.
The second thing you need to do is use RDF to describe the remaining (finite)
set of URIs. Somewhere at the top of the URI path hierarchy you create a
resource that lists or allows query over the set of users. If that's not
appropriate, you give your user an explicit URI to their representation in the
URI space. I, for example, might reside at "https://example.com/fuzzyBSc". At
that location you place a resource that explains the rest of the hierarchy,
namely:
<bookmark-service
xmlns="http://example.com/documentation/service"
rdf:about="https://example.com/fuzzyBSc"
>
<recent rdf:resource="https://example.com/fuzzyBSc/bookmarks/"/>
<all rdf:resource="https://example.com/fuzzyBSc/bookmarks/all"/>
<by-tag rdf:resource="https://example.com/fuzzyBSc/bookmarks/tags/"/>
<by-date rdf:resource="https://example.com/fuzzyBSc/bookmarks/date/"/>
<tags rdf:resource="https://example.com/fuzzyBSc/config/"/>
</bookmark-service>
Separately, and tied to the rdf vocabulary at
"https://example.com/documentation/service" you describe how to construct queries
for the by-tag and by-date resources. I don't even mind if you use the braces
notation to do that (although clearly more information than just the name this
method provides will be required, for example a date type wouldn't go astray!):
<URIQueryConstruction>
<!-- tag={tag} -->
<Param name="tag" type="xsd:string">
</URIQueryConstruction>
<URIQueryConstruction>
<!-- Y={Y}&M={M} -->
<Param name="Y" type="xsd:integer">
<Param name="M" type="xsd:integer">
</URIQueryConstruction>
Alternately, you make https://example.com/fuzzyBSc/bookmarks/tags/ contain a
resource that represents all possible sub-URIs. Again, this would be a simple
RDF model presumably encoded as an RDF/XML document. Another alternative again
would be to incorporate the tags model into the model at
"https://example.com/fuzzyBSc/".
So I know that https://example.com/fuzzyBSc/bookmarks/tags/?tag=shopping
(or https://example.com/fuzzyBSc/bookmarks/tags/shopping at the implementor's
discretion) will lead
me to shopping-related bookmarks owned by me, and that https://example.com/fuzzyBSc/bookmarks/date/?Y=2005&M=05 will fetch me this month's bookmarks.
Personally, I think that some REST proponents are confusing (finite) regular
URI and (infinite) query URI spaces too much. There are important distinctions
between them, particularly that you can deal with finite spaces without needing
client applications to construct URIs using implicit knowledge that might be
compiled into a program based on an old service description or explicit
knowledge gleaned from the site.
The RDF approach (when available) allows sites to vary the construction of
these finite URIs from each other so long as they maintain the same RDF
vocabularies to explain to clients which resources serve their specific
purposes. The substitution approach must always follow the same construciton
or a superset of a common construction. This is probably not so important for
a very specific case like this bookmark service, but may be important for
topics of wider interest such as "how do I find the best air fare deal?".
Using the RDF approach allows you to navigate using a very general scheme with
few constraints on URI construction to sites that require detailed knowledge
to be shared between client and server to complete an operation.
Update: A
link
summarising various current attempts
Benjamin