Bare Minimum RESTful WFS

I get glimpses of discussion on the non-public WFS Simple/Basic email list about a RESTful makeover for the protocol. We're going to see more and more of this as the developers of all public-facing services realize that they need at least a minimal RESTful aspect. Here's what that looks like for WFS:

  • To read (or query) use only HTTP GET

  • To publish use only POST and PUT

  • Always put request scoping parameters in the URL

  • Always express error conditions in HTTP response headers

What about complex filters with OGC XML expressions too long for the query string? First of all, this is a WFS bug and web server bug, not a REST bug. I've got some ideas about how to solve this using resource-oriented design (future post), but will stick to basic REST here.

RFC 2616 states:

The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line. POST is designed to allow a uniform method to cover the following functions:

  • Annotation of existing resources;

  • Posting a message to a bulletin board, newsgroup, mailing list, or similar group of articles;

  • Providing a block of data, such as the result of submitting a form, to a data-handling process;

  • Extending a database through an append operation.

Does this invite us to POST filters after all? No. The WFS filters help describe the scope of the request. They are not part of the representation of a new resource, or data to be processed. Splitting request scoping between the URL (typename, bbox) and the request body (posted filters) seems to me to be the worst of both worlds. Better to put all scoping in the HTTP request body (if you must) and call it XML-RPC or SOAP, or put it all in the URL and call it RESTful.

Similarly, a RESTful WFS has to take advantage of the response status header. Its clients are HTTP clients first and foremost, not WFS clients. If the client sends a mangled request, reply with a 400 Bad Request. If the WFS filters screened out everything, reply with 204 No Content. By all means, do put a more verbose message in the response body, but the status header is more important to an HTTP client.

Ignoring service capability and feature type metadata for the moment, the above is all that's needed to produce a basic REST-RPC hybrid service.

Comments

Re: Bare Minimum RESTful WFS

Author: Bill Thorp

Whats the return type of your RESTful GET? Can it be JSON, so that browsers can eat WFS's across domains via script-tag injection? Maybe a thin JSON wrapper of SVG, VML, or canvas? At what point to do stop catering to client implementation?

Re: Bare Minimum RESTful WFS

Author: Sean

Good question. I think one flavor of JSON + GML would cover a lot of bases. The former is handy for browser clients, and the latter can be transformed to almost anything else by more capable clients.

Re: Bare Minimum RESTful WFS

Author: Jason

How's this: the OGC Filter can be POSTed -- it is a representation of a subordinate resource to the GetFeatures resource. The GetFeatures operation re-done RESTfully is a "features" resource -- all the features available. A Filter is a representation that, er, represents a sub-set (subordinate) of the "features" resource. It's not the only representation. There's also the GetFeatureById (I think) operation that represents a subset of "features" just using a different representation...

Re: Bare Minimum RESTful WFS

Author: Sean

Yes, that's pretty much what I was going to suggest in a future entry. Put filters to a subordinate resource like /wgis/{typename}/queries/{name}, and then read them like filtered sub-types. It's not a foreign concept at all. Many of us use watchlists or saved queries in other web applications. The trick would be to do it without keeping client state on the server.

Re: Bare Minimum RESTful WFS

Author: Jason

You could avoid Filter and attempt CQL, but I don't think CQL has much traction with implementers(?). CQL would fit nicely in a HTTP/GET query string, tho. Still bothering me is the fact that POSTing a Filter to a "features" resource, ought to result in the creation of a new (sub-ordinate) resource. But this never happens. The result set is created, sent back to the client and forgotten about usually. Does this violate the whole POST/Filter strategy?? Alternatively, the GetFeatures operation could accept a URL that points to a Filter instance (on my server -- my shared/saved/bookmarked filters) instead of me sending it. That Filter URL could be used with HTTP/GET more easily than CQL perhaps. The stored query works nice in Catalog (maybe WFS has this too?). Basically a pre-cooked Filter on the server waiting to be parameterized with the HTTP/Get query string. This seems good n' RESTful, but that stored query must pre-exist on the server. A small number of stored queries would actually satisfy most search use-cases, but the primary mode of today is to just sending along big/ugly filters every time. Perhaps, if this shifts -- user-agents using the stored query as a rule not the exception -- then POSTing a Filter would actually mean something like: "Oh, you want ME, the server, to support a new Filter? Well, OK. Here's my response that contains your freshly baked URLs that you may use to execute that Filter". This way, the POSTing would create a new HTTP/GET URL for the resource (features) satisfying the filter that was previously POSTed.