REST reduced to a URL with a “bunch of parameters”

Don’t get me wrong. Exposing an HTTP GET interface and supporting query string parameters is a wonderful thing for building mash-ups and bookmarking, but it’s only the tip of the iceberg to being truly RESTful.

FeatureSever is software that allows users to obtain information about geographic features using a RESTful API. Here’s a few examples of the kind of URLs FeatureServer exposes:

http://example.com/featureserver.cgi/scribble/1.atom
http://example.com/featureserver.cgi/scribble/1.kml
http://example.com/featureserver.cgi/scribble/1.gml
http://example.com/featureserver.cgi/scribble/1.json

“1” is a feature identifier (e.g. my house). Note that these URLs aren’t terribly RESTful, although they are easy to use and understand. Why aren’t they RESTful? The URL isn’t suppose to indicate the nature of the representation (the R in REST), in this case Atom, KML, GML and JSON, each of which has its own designated mime media type. This goes against the URI Opacity best practice. Each of these URLs represents the same resource (my house), but they can represent it differently in GML, KML and even a old-fashioned HTML page would be possible.

If FeatureServer were more RESTful, there would only be one URL:

http://example.com/featureserver.cgi/scribble/1

And the mime-type request would move to the HTTP request header “Accept”. Here’s a version that requests feature “1” in KML:

GET /featureserver.cgi/scribble/1 HTTP/1.1
Host: example.com
Accept: application/vnd.google-earth.kml+xml

So why didn’t they do it this way? Setting the “Accept” HTTP request header is impossible to do in an HTML <A> tag even though it performs an HTTP GET. It’s also impossible to set via the <FORM> tag. Specifying the mime type using the URL is simply easier and easier wins the day.

As software is written to understand more alternative media types, especially machine-readable types like RSS, this may start to cause problems. If there are two URLs for “my house”, then which URL do I bookmark? Firefox might bookmark the “.html” version, but my Map reader might prefer the KML version. Two URLs for the same thing.

How would I determine how popular “my house” is on the web by finding backlinks? I’d need to put this in the Google box:

link:http://example.com/featureserver.cgi/scribble/1.[Every media type here]

That’s not an ideal way of keeping track of things.

5 comments on “REST reduced to a URL with a “bunch of parameters”

  1. Agreed, it’s not restful. But Content negotiation sucks balls. The restful part is that you can post content to those URIs, and it will save it, or you can call DELETE on them, and it will delete them. The multiple formats is an important part of how FeatureServer works, but not part of its RESTful nature.

    I’ll add support to fall back to content negotiation soon. I’ve filed ticket #1 in the FeatureServer ticket tracker for it.

  2. Okay, I’ve set up SVN to post-commit checkout to a server running on port 8095 of featureserver.org, and you can see the result:

    curl -H “Accept: text/html” http://featureserver.org:8095/scribble/1

    Will now ship HTML.

    Note that this does not support the full accept header semantics: specifically, it’s an exact match. The reason for this is that FeatureServer’s JSON mode should be the default when something else isn’t explicitly requested, and browsers send text/html in their accept header by default. This would break existing applications which are depending on the behavior that currently exists. So, although it is slightly more RESTful, it’s still kinda ‘eh’ as far as purism goes. Luckily for me, I’m not a purist.

    Does this bring things closer to what you were thinking should be the ‘way things work’?

  3. Thanks for the comments! That URL isn’t working right now, I’ll try it tomorrow. Yes, the browser sends all kinds of content types in the Accept header; You could set these headers with an AJAX call. One redeeming thing about it (AJAX), I suppose…

    Just curious, how would FeatureServer handle variant GML schemas? Catalog has these same problems. In the OGC Catalog work, you can use the HTTP Accept header, but you can also specify things like “output schema” and “element sets” which also modify the representation. These are set by using the URL query string for HTTP GET or encoded an XML request if using POST. The GET version modified the URL (not a good practice) while the POST version uses the wrong HTTP verb… 🙁

  4. Using the URL (for content negotiation) as a substitute to an unavailable “Accept” header override in the browser dominant http world is IMO a good compromise.

    The browser sends an Accept header of */* for all practical purposes. And although admittedly unRESTful, the URL is the only available alternative. Any others and I’ll be all ears.

  5. Essentially, it wouldn’t. The GML support in FeatureServer is a lightweight chunk of code designed only to support OpenLayers. I don’t care about GML, I think it’s a waste of time, but it was expedient to include it.

    Sorry about the broken URL — the one that works is http://featureserver.org:8095/scribble/2 . (I changed datasources to be the same source of data as the main source that is on the FeatureServer demo, and forgot that I’d deleted ID 1 in testing. :))

Leave a Reply