Wednesday, 14 April 2004
A(nother) Description Format for REST
I’ve talked before about describing RESTful Web resources, going as far as prototyping a new format. That work was predicated on the assumption that WSDL wasn’t adequate.
However, Dave Orchard has been looking at this in the WSDL WG, and recently challenged me to think about it again. I’m becoming convinced that it would be workable. To give an example (using my usual yardstick, an online address book);
<portType name="AddressBookEntry"> <operation name="getHTML" web:Method="GET"> <output message="tns:AddressBookEntryDocument" wsa:Action="urn:ietf:params:mediatype:text/html"/> </operation> <operation name="getVCard" web:Method="GET"> <output message="tns:AddressBookEntryVCard" wsa:Action="http://www.w3.org/2001/vcard-rdf/3.0#"/> </operation> <operation name="putVCard" web:Method="PUT"> <input message="tns:AddressBookEntryVCard" wsa:Action="http://www.w3.org/2001/vcard-rdf/3.0#"/> </operation> <operation name="delete" web:Method="DELETE"> <output message="tns:StatusResponse" wsa:Action="http://www.example.org/resourceStatus"/> </operation> <operation name="editFormSubmit" web:Method="POST"> <input message="tns:EditFormContents" wsa:Action="http://www.example.com/editform"/> <output message="tns:EditFormStatus" wsa:Action="http://www.example.com/editstatus"/> </operation> </portType>
There are two things happening here; the new web:Method attribute is used to identify the generic method of an operation, while wsa:Action (courtesy of WS-Addressing) is used to identify different types of representations available (an analogy to media types).
Together, they allow you to model individual Web resources as portTypes, sprinkling metadata on operations to indicate that they’re interactions regarding the state of that resource. The nice thing here is that unlike operation name overloading (e.g., name="getFoo"), everything is in extensions; you can still name your operation “getStatus” or just plain “Status” if you want to. The only constraint on operations is that each one needs to have a unique (web:Method, input wsa:Action, output wsa:Action) tuple.
It’s important to note that all operations aren’t required to be RESTful; it’s easy to imagine scenarios where part but not all of the interface of a resource has generic semantics. The default web:Method might even be able to be POST, depending on how you look at it.
Of course, there’s a lot this doesn’t cover. For example, some standardised SOAP Faults that are rough analogies of HTTP response status codes (e.g., Not Found, Operation Not Supported, various flavours of Redirect) would be a good start. I’m also not yet sure how to handle generative naming; it was easy to layer into my from-scratch format, but doing it in WSDL is a more subtle problem.
On a related note, there are cases where you’d want to model some operations on a portType as affecting the state of the “primary” resource, while others will affect the state of subresources. For example, it would be nice if getCar and getCarDoor were operations on the same portType, but available as different resources, /car and /car/door. This could be handled by adorning operations with an identifier for a subresource and then doing the actual mapping to the URI space in the binding, or in service-specific policy.
Finally, there is as of yet no way to talk about the relationships between resources that are modelled as portTypes; I imagine that this is where orchestration would come in.
Does this seem reasonable? One interesting test would be to see how applications like Jon Udell’s LibraryLookup and the Atom API would be represented in such a format. Any comments from either the Church of REST or the United (heh) Congregation of Web Services appreciated.