Once in a while I come across someone talking about RESTful URIs. A URI is just a name. What can be RESTful about it? Then there are threads like Query string format wondering about RESTful way of constructing URIs.

There is a perception that

  • URIs that organize information hierarchically,
  • URIs that are human readable,
  • and URIs that do not use query parameters

are RESTful while URIs that don’t follow the above are ugly, un-RESTful and must be avoided. Under this perception, a URI such as

is considered more RESTful than

Similarly a URI such as

is considered to be RESTful while a URI such as

is not.

This is a baseless perception. Syntactical differences in these URIs do not make one RESTful and the other not. Is the first URI cleaner than the second? May be, but without formally defining what "clean" means, it makes no sense to argue.

There is also an argument that query parameters offer a "weak source of identification". However, given that URI rewrite rules can be used to transform query parameters into path segments and vice versa, I don’t find this view compelling enough to abandon query parameters.

For URI design, what is more important is to encourage client applications to treat URIs opaque without necessarily obscuring information for the sake of opacity. Before elaborating on these, we need to understand what opacity does not mean.

In the past, there were some lengthy and heated debates about URI opacity and whether this concept is a myth. See, for example, OpacityMythsDebunked, which points out that URI opacity "discards the important and useful concept of structured naming and semantically rich namespaces". I find that such arguments are incomplete unless we ask "opacity for whom?" and "for what purpose?".

For the server, it is beneficial to organize resources in hierarchical namespaces, if it makes sense. It is a reasonable approach to design URIs in an orderly (whether hierarchical or not) manner. But URI opacity does not mean URI obscurity!

It is true that URIs can not be completely treated as opaque. Query, matrix, and template parameters are exceptions. Nonetheless, for the client developer, it is beneficial to treat URIs as opaque. Instead of computing URIs from scratch or guessing URIs from other URIs known to exist, the client should rely either URIs given to the client via hypermedia or URI templates, or other well-known means of constructing URIs with the most common example being HTML forms. The key point of URI opacity is decoupling between client and server applications.

As I was arguing for opacity of URIs, one of my colleagues questioned about human readability. What is more important? Readability or opacity? I think both are important and can be achieved. The server can provide human-readable URIs, but instead of forcing clients to dissect URIs, it should provide hypermedia and/or URI templates so that clients can construct URIs with minimal effort. I find human readability without any regard for opacity from client’s perspective less useful.

Write a Comment


  1. What I mean is that if you update by POSTing to then you are really using URIs to identify methods, not resources, which you identify instead by using an app-private identifier (a numeric ID in this case) passed as a parameter in the query string. This is the CGI style and is a REST-RPC hybrid rather than a RESTful system: the resource is subordinate to the actions that operate on it.

  2. “I agree. That’s a good litmus test.”

    Of course it is. And that was the point of the “argument” you refer to, but failed to quote – if you avoid query params such problems, including redundant rewrite rules, go away. It’s not just a matter of taste.

  3. The litmus test that Aristotle was referring to is to use different URIs for different operations. I don’t think the issue was query parameters per se. At least that’s how I read his comment.

    I don’t think rewrite rules are redundant or can go away since there is a lot of software that can only deal with query parameters.

  4. There are a few differences, mostly minor.

    If you don’t set explicit freshness information (Expires or Cache-Control), a cache will treat a response with a query parameter as uncacheable.

    In theory, this should only happen when the origin server is HTTP/1.0; in practice, it happens for 1.1 servers as well, because Via isn’t well-implemented, and caches need to be conservative.

    Many existing cache deployments will consider all URLs with query parameters to be uncacheable, period.

    The other practical difference is that URIs with query parameters doen’t work as well as relative references. Sometimes a minor optimisation, but sometimes important (especially when you’re trying to convince someone that using URIs as identifiers doesn’t add a lot of overhead).

    There’s also a (very soft) human perception impact; people tend to think that things with query parameters may change, based upon their previous experience. Only an issue if people will see your URI…