Web Service Operations Language (now obsolete)

NOTE:::: I think that this has already been made obsolete by a similar idea with a better model. See WRDL.

Abstract

The basic model of a REST Web Service is that services are described as webs of documents. Typically the documents will be dynamically generated but that is not necessarily the case. Just as with services based on COM, CORBA or SOAP, it would be nice to have a declaration of a service's operation in advance so that reliable software can be constructed with less testing.

Insofar as a service consists of documents, especially XML documents, XML schemas provide a partial description of the service. What they do not describe is the transitions from one document to another. That's what WSOL does. It is intended to be the IDL/WSDL for HTTP web services. Just as with IDL it may one day make sense to "bind" WSOL into a statically typed programming language to make the construction of type-incorrect client software more difficult.

Model

Think of a web service as a web of document types. The "find airline seat" document points to the "reserve seat" document through a URI. That document points to the "purchase ticket" document through a URI and so forth. Each document has associated with it an XML Schema but also a operation description (or perhaps just a fragment of a operation description ). The "root" operation description for a service asserts that a particular URI references a service that conforms to a particular operation description. As you move from document to document following links, each link is strongly and statically typed by the operation Description. A failure to conform is a runtime error, just as with non-validation against an XML Schema or WSDL service desctiption.

Sometimes the client wants to send information to the server. HTTP allows you to do this either by POSTing to a document or PUTting to a URI provided by the server. So beyond being strongly typed, each URI must have associated with it a set of possible methods and inputs. Think of this as a 4-tuple:

WSOL will help the service provider to define these valid inputs in advance so that client software can be reliably constructed.

Sometimes you have an option of PUT and/or POST and/or DELETE so we must have multiple possible input actions associated with each URI. The input to PUT is likely to be very different than the input to POST and DELETE or GET have no body inputs. WSOL will allow that.

Once the HTTP request has been made, a response comes back. In order to build robust, statically typed, services we want to know what valid range of responses are legal. So for each sort of input, a range of valid outputs may be described. These consist of HTTP response and body content (perhaps constained to one or more XML vocabularies). If a statically typed programming language has data binding then one can imagine that each "type" of input maps to a particular method and the result of the method would be either an XML DOM or the statically typed result of the data binding. (e.e. IPurchaseOrder instead of IDOMDocument). To make this binding easier, input types should be named, similar to operations in WSDL.

The fundamental difference between this model and WSDL's is that this is about interactions between web service components (every page is a component) whereas WSDL is about describing a single web service component. If you recognize that ever WSDL "service" is a single web page you can see how poorly that model integrates with today's Web.

Choosing a document type rule

A WSOL document is composed of document type rules in an element called <doc-rule>. Each rule has two parts, an attribute called "match" and some content.

The match pattern is used to know when a rule applies to an XML document. It is an XPath applied to the root node of the document. For streaming purposes it may be restrained in a future version of this specification.

For example, a document type might be "airline ticket purchase contract." It may be recognized by the fact that it has a particular root element:

<doc-rule match="airline:purchase-ticket"
            xmlns:airline="http://www.someairline.com/">
    ....
</doc-rule>

The XPath language is extended with these functions:

http-header(string)
returns the value of an HTTP header that came with the document when it was retrieved (or the empty string if it was retrieved without HTTP).
http-reponse-code()
returns the value of the HTTP response code that came with the document when it was retrieved (or the empty string if it was retrieved without HTTP).
content-type()
returns the content-type that came with the document when it was retrieved, or a content-type known through stored metadata.

All three of these functions apply even to non-XML documents. Other XPath functions, axes and operators that depend upon an XML infoset will cause an error.

Associating transition rules with URI nodes

Each document type rule has within with it a variety of URI handling rules. Each such rule consists of an > attribute called "match" (also an http-extended XPath) and a set of operations.

<doc-rule match="airline:purchase-ticket"
            xmlns:airline="http://www.someairline.com/">
    <uri-rule match="a/@href">
        ....
    </uri-rule>
    <uri-rule match="img/@src">
        ....
    </uri-rule>
</doc-rule>

The content matching pattern selects some set of nodes in the document. When the rule is applied at runtime, these nodes MUST contain URIs. The purpose of each rule is to define what happens when a particular HTTP method is applied to each URI.

A future version of this specification will describe a way to combine WSOL's with XML Schemas so that the definition of a node's operation is tied to its type declaration rather than through an XPath.

Operations

A operation is an element called "operation". Each operation consists of three parts, a unique name, an input description (an element named "input") and a set of output descriptions each an element called "output". The name attribute is so that a WSOL aware language could invoke the action merely by providing the name.

An input description consists of an HTTP method, an optional set of query parameters, an optional set of HTTP headers and an optional document/media type. If values are not provided for a query parameter or an HTTP header then it must be supplied by the application.

<doc-rule match="airline:purchase-ticket"
            xmlns:airline="http://www.someairline.com/">
    <uri-rule match="ticket-purchase">
        <operation name="buy_ticket">
          <input method="POST">
            <query-param name="foo" value="bar"/>
            <query-param name="foo2"/> 
            <header name="Message-id"/>
            <header name="Pragma" value="no-cache"/>
            <doc-type match="content-type()='text/foo+xml'"/>
          </input>
            ....
       </operation>
       <operation name="cancel_purchase">
          <input method="DELETE"/>
           ....
       </operation>
    </uri-rule>
</doc-rule>

At runtime, the client application applies some business logic (e.g. I want the "window" not the "aisle") and chooses a URI from the retrieved document. Given the URI, the WSOL engine knows the set of appropriate operations. The client application must then issue an HTTP message conforming to one of them. If it issues any other message then it is in violation of the operational specification. Implementations are encouraged to use the WSOL document to make application coding easier. For instance it could be compiled into an interface library or loaded at runtime in a dynamic language.

An output description consists of an HTTP result code, a set of HTTP headers and a document type. If the real output does not match one of the output descriptions associated with the selected input description then it is in violation of the operational specification. If the output has a document type then the whole process begins again.

<doc-rule match="airline:purchase-ticket"
            xmlns:airline="http://www.someairline.com/">
    <uri-rule match="ticket-purchase">
        <operation name="buy_ticket">
          <input method="POST">
            ....
          </input>
            <output name="standard" result="OK">
                <header name="Location"/>
                <doc-type match="content-type()='text/bar+xml'"/>
            </output>
       </operation>
       <operation name="cancel_purchase">
          <input method="DELETE"/>
           ....
       </operation>
    </uri-rule>
</doc-rule>

Todo:

  1. This is way too informal, of course. It needs a proper XML schema etc.
  2. Need an inclusion feature so that you can think of chunks of functionality as reusable modules. For instance you would include the credit-card company's modules to get
  3. Need wildcards. Sometimes you really don't know what you're going to get back when you follow a link.
  4. Looks to me like this is amenable to a GUI...product potential?
  5. What is the prior art here? Hypercard? State transition diagrams for lexers/parsers?