REST, Hypermedia, and Query Strings

Are links embedded in hypermedia always immutable? What about the query string part of it? That question came up recently in our shop.

Now, I agree totally that the path part of the URI — that is, everything in front of the first “?” or “#” should be treated as an immutable, opaque string. That’s just saying that the server controls that part, and can change it at a moment’s notice. The client must be decoupled from the path of the URI. But the query string part of the URI is not so clear.

One point of view (from a really smart guy, so I respect his opinion a lot) was that URIs embedded in hypermedia are absolutely immutable, front to back. It’s the server’s responsibility to provide all the possible links a client could want, and the client just deferences those links as totally opaque strings.

For example, for paginating a resource that was a big list, someone stated that the server should send hypermedia that contained a full list of URIs to every page available. If that was 100 links, OK. If that was 1000 links, OK. But the client shouldn’t be able to pass a query string with an arbitrary offset and number of items to pull. Altering the query string constituted altering the URI, and was forbidden by the rules of REST.

(We were even threatened with losing our place at Level 3 of the Richardson Maturity Model of REST… but I’ll save that for another post.)

Unfortunately, that view of query strings doesn’t fit with how query strings are actually used in the most important hypermedia type of all, HTML.

HTML provides several ways to link to other hypertext pages:

  • an <a href> with a static link,
  • a <link> element with a static link
  • and a <form> element that takes user input and constructs a query string, appended to a static link.

But HTML is still a hypermedia type.

In the REST world, the way to look at query string parameters is as qualifiers that change the scope of the underlying resource.

Search is a classic example, and one that is cited as problematic for REST. Because search requires free-form search criteria, and there is absolutely no way to present the client with a full list of searchable terms (well, I guess you could, but the list would be thousands and thousands of links long)… the client just has to pass the search criteria in the query string. So does that break REST’s hypermedia constraint?

But search is not a difficult case for REST — or even a special case — because the resource is EVERYTHING THAT WE’VE EVER INDEXED. That would be a lot of data to return at once. The search query string narrows the resource to just what we’re interested in. Taking the purist’s view, for a big resource, would simply be too expensive to anticipate every query the client might be interested in.

So “query” string is very intentionally named. There has to be a way to parameterize GET requests to the server, so the server knows what you really want.

Back to pagination: If the resource is a big list, it’s reasonable & consistent with hypermedia to apply a filter and say “Only show me the 10 items starting at item 110″. The larger resource is still the same, we’re just narrowing what we return.

That said, changing state with query string values is obviously way out of bounds!

Or another way to look at it is, URI definition allows for “matrix” parameters which are non-hierarchical name-value pairs that are in the “static” or “identifying” part of the URI. So why would we need a query string at all?

Ultimately, we’re going to have to get away from these stupid discussions about the limits that REST requires, and talk more about how to be smart with hypermedia.

About these ads

7 Comments

Filed under Uncategorized

7 responses to “REST, Hypermedia, and Query Strings

  1. Pingback: This Week in #REST – Volume 35 (Mar 7 2011 – Mar 26 2011) « This week in REST

  2. Donald Smith

    This topic is surprisingly difficult to find much information on. Most of the REST books seems to leave off the query and search parts that a REST API always seems to require. I have heard of two options to handle this problem:

    1. Embed a FORM with the available query string params into the representation.
    2. Provide a link to a representation explaining the query params available.

    I also like the idea of matrix URIs, but I am unsure of how to implement. Each API seems to define a whole new set of params that require out-of-band knowledge and tight coupling.

    I am still unsure which is the most RESTful approach.

    • roby2358

      Ya I agree. I think this is kind of a blind spot that comes from the community focusing on URL definition and verb usage, and forgetting about the hypermedia constraint.

      (Anymore, I put aside the “REST” boogeyman, and say, let’s talk about hypermedia.)

      Here’s a page that is great for expanding on what we expect from hypermedia:

      http://amundsen.com/hypermedia/hfactor/

      In the end, and I think this is the thing that pushes the conversation into a blind spot, a URI with a “searchable” portion requires a signature. Providing a FORM like you suggest is the most immediate and obvious way — that’s what HTML did. But others say that the signature (i.e. parameter definitions) should come from another source.

      Taking the simplest case and treating URIs in hypermedia as opaque, immutable strings just runs aground almost right away. It seems to me like we should be tackling the problem head-on.

  3. Donald Smith

    I agree that treating URIs as opaque strings with regards to searching does hit a road block rather quickly. I don’t really like pointing to another source that explains the query params. It seems like it becomes a part of the media-type which requires far too much coupling. I also do not like URI templates for the same reason, the client code must be written to handle the substitution.
    At this point, I don’t feel like there is a solid solution that doesn’t require out-of-band knowledge or tight coupling of the client.

    • roby2358

      I have the same feeling. The parameters declaration for a URI *could* be treated as a separate resource, but it just seems odd. Or it could be part of the OPTIONS response. But, again, that requires another call & an understanding of what comes back. It seems more flexible to me embedding that info into the original hypermedia, just like HTML does.

      Fielding talks somewhere about part of the price to pay for hypermedia is effeciency. Engineers sort of compusively try to consoliate information, because they’re good at doing that, but that runs counter to some of the goals of hypermedia. Look at HTML, and how many identical

      and elements fly across the web every day.

      Maybe there’s a hybrid approach, where the hypermedia can spell out the parameters, or else specify a link to the signature for a queryable URI. i.e. treat the signature as *another* resource. But I have the same sense as you — that breaking that up just adds complexity and coupling to the interaction.

      • Donald Smith

        Yes, I fight the battle of efficiency with my team everyday. It is very hard to get non web engineers to understand, but I try anyway.

        I have settled on OpenSearch to handle the queries for the API I am working on. I really like the approach of using the template URIs. It keeps the server side implementation away from the client. The client doesn’t need to understand or care about the structure of the URI. The client only needs to understand the OpenSearch params and the extensions that I publish in a separate document linked from the representation. The key is that the client doesn’t need to build up URIs or hard code anything.

        Recent discussions with a few developers that will consume our API got me to start thinking about a different problem. I have gone to a lot of trouble to remain RESTful on the server, but these guys are already doing bad things in the client. I immediately thought, how can we test clients to make sure they conform to the REST style. I thought it would be interesting to create a variant of our production API served from an alternate endpoint that could test the client. This implementation would generate random URI’s in the responses instead of the fixed names that are seen in our production environment. Should be quite telling.

        Anyway, thanks for the banter.

  4. Pingback: How do you measure the RESTful-ness of an application? | ITPark

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s