mark nottingham

URI Templating, the Spec

Wednesday, 4 October 2006

Internet and Web

As mentioned a while back, there are a variety of places where it would be useful to be able to describe the structure of a URI, rather than just convey a URI itself. I took a stab at this in the Link Header draft, and have also been working in the background with DeWitt Clinton, Joe Gregorio, Marc Hadley, Dave Orchard, and James Snell on a more general specification, URI Templates, the first draft of which we (finally!) got published today.

The idea behind URI templates is blindingly simple. There are lots of conventions that people use to denote the variable parts of URIs; one of them is to use {brackets}. All that we’ve done is codify that practice (brackets are a good choice because they’re not allowed in URIs, so there isn’t much risk of collision). For example,

http://www.example.com/users/{userid}/friends

Conceptually, a URI Template has a lot in common with forms (whether HTML or X), but they have a few advantages;

What benefit does this bring? Besides having a common convention for human-readable documentation (which IME is already pretty common), the real value is when templates are used by machines.

Marc Hadley’s WADL is a great example of this. Another is the Link-Template header, which allows you to build URI-centric protocols around link templates.

For example, lots of HTTP services will redirect you to an authentication URI, where you get a token in exchange for your credentials (the recently-released BBAuth is a good example of this). As part of that exchange, you need to communicate to the authentication server where to redirect the user after they successfully present credentials. E.g.,

http://www.example.com/signIn?onSuccess=http://other.example.org/i-want-to-go-here/

Right now, the way to do that is documented in prose. The problem is that there’s more than one authentication service out there, and each takes its arguments in a different form. Now, eventually we could come up with a general “third-party URI-based authentication” specification that everyone could implement, but the problem is that if such a beast existed, it would need to tell people how to form those URIs.

If the service you originally tried to use (you know, before you got redirected) returned a link template with the redirect;

HTTP/1.1 302 See Other
  Location: http://www.example.com/signIn?onSuccess=http://service.example.com/myService
  Link-Template: <http://www.example.com/signIn?onSuccess={success_uri}>; rel="login"

you’d have the best of both worlds; a user accessing myService directly would get authenticated and their browser would automatically follow Location to to back to where they started (but with the right credentials), and a third party (the BBAuth case) would be able to change the Location header they send downstream, based on the Link-Template, to send the person to the right place.

Similarly, you could use a URI-encoded template inside of success_uri to communicate to the authentication server where the login token should go.

Of course, there are a lot of caveats about this approach to authentication, but the important thing here is that URI-centric protocols like this can be constructed without stomping on URI opacity, if the right techniques are used. I have a feeling the same techniques could be very useful in APP, among other places.


8 Comments

Jerome Louvel said:

In the Restlet framework we will soon support URI templates as the way to easily extract variables from incoming target URIs.

So, if you declare this template http://www.example.com/users/{userid}/friends and an incoming call has a target URI of http://www.example.com/users/1234/friends, then the “userid” attribute will be added in the call’s attributes map with the “1234” value.

Refs: http://www.restlet.org http://restlet.tigris.org/issues/show_bug.cgi?id=162

Thursday, October 5 2006 at 1:02 AM

M. David Peterson said:

This is absolutely brilliant!

Friday, October 6 2006 at 4:07 AM

Nick Thompson said:

nice, a standard here would be very helpful!

i’ve built an url templating mechanism, and the thing i’ve found kind of inconvenient is quoting - different templates require different quoting mechanisms, and you’d like to leave the quoting style up to the person who provided the template rather than up the application providing the variable values.

i.e. you’d like to allow url templates either like this: “http://foo.com/app/{x:path}/action” or like this: “http://foo.com/app/action?x={x:query}”

where “path” and “query” are two different quoting rules on the same variable “x”. generally the draft allows an application to do this, and in many cases it seems like the quoting rules will be application-specific although some will be very common. the application here has to anticipate the possible quoting needs, but the template provider still gets to choose between them.

anyway, although the spec allows for this, having some kind of separator char to divide the variable name from the context hint is nice. i see that variable names are limited to “unreserved” characters which don’t allow much room for structure in variable names. is there any reason not to widen that a bit?

Sunday, October 15 2006 at 1:28 AM

pwb said:

This discussion reminds me of a recent concern of mine: the proliferation of RoR-style URIs (e.g., http://www.example.com/users/{userid}/friends). Shouldn’t we just use standard HTTP querystrings here? You know, like this: http://www.example.com/getfriends?user={userid}.

These have the benefit of being a) consistent with HTTP, b) more RESTful, c) callable with s, d) self-descriptive, etc.

Monday, October 16 2006 at 8:37 AM

pwb said:

It just seems like HTTP has a mechanism for this: querystrings. The part that got gobbled was that when querystrings are used, you get some extra funcitonality in being able to make form-get requests with selects and options.

Mashing everything between /s seems to be a new contruct that’s maybe a bit prettier but not much else.

Thursday, October 19 2006 at 12:11 PM

Marc Brooks said:

For those that wonder about an implementation of this you can use right now, I’ve written a simple opne-source implementation for .Net (1.1 or 2.0) that can read about it on my blog. Just Google musingmarc

Friday, June 22 2007 at 10:38 AM