whenToUseGet-7 Making SOAP Restful

I'm delighted to see the tone of this discussion improving.  The purpose 
of this note is to share some (half-baked) ideas on how SOAP and REST 
might work well together.  These thoughts are mine, and don't represent 
positions of either the protocols workgroup or my employer. 

BAD NEWS:  Long Note Warning
POSSIBLY GOOD NEWS:  It's long because it contains a specific (if very 
tentative) proposal

By the way, I really like Larry M.'s rewording of Dan's proposal.  I think 
it's quite complementary to what I've written below.

Background
----------

The proposal will make more sense if you have reviewed the latest drafts 
of SOAP 1.2 [1,2] (I am pointing to the editors drafts.  They have no 
official standing but are public and representative of the workgroup's 
latest thinking.)  In case you don't read them, here are the pertinent 
highlights.  Skip ahead to the proposal if you know all this:

* SOAP used to be mainly RPC.  Now it is primarily a messaging framework. 
An RPC convention is described, but optional.  This proposal therefore 
focuses first on making SOAP messaging RESTful.  RPC is discussed built on 
that substrate.

* SOAP distinguishes the so-called request/response message pattern from 
RPC.  RPC is a specific use of request/response, optimized to the 
representation of method invocations (parameters, return values, etc). 
Non-RPC request/response is a very important use case ("send purchase 
order document, get response document" -or of more concern to the rest 
community - "get price list document").

* SOAP is designed to work over protocols other than HTTP, and to support 
scenarios in which a request arrives (probably from the public network) 
through HTTP, and is then further routed through other protocols (perhaps 
MQSeries).  You write new "bindings" [3] to describe the mapping of SOAP 
to a protocol. 

*** SOAP envelopes are Infosets, not angle brackets.  The binding can move 
the envelope information in any way it wants.  This is key to the proposal 
below.

* One of SOAP's great strengths in comparison to HTTP is the richness of 
its header and extensibility architecture.  In addition to use of XML 
syntax, it provides mechanisms (mustUnderstand) to facilitate the safe use 
of extensions in combination.  Capabilities such as digital signatures, 
authentication, transaction control, etc. can be encoded using these 
facilities, and MAY be implemented end-to-end when going multiple hops 
(e.g. MQSeries + HTTP).

* FWIW:  I believe it's fair to say that something like 90 percent of the 
SOAP working drafts are not at issue in this discussion.  The REST 
question relates primarily to the specific HTTP binding that has been 
proposed, and to the implications for the (optional) RPC facilities.  That 
said, the proposal below attempts to point a direction for making SOAP 
more RESTful, not just on HTTP, but with any other RESTful underlying 
protocol.


A Proposal for RESTful SOAP Information Retrieval
-------------------------------------------------

This proposal is different from some earlier ones, in that it makes no 
attempt to encode SOAP bodies in a URI.  On the contrary, it makes the 
conservative assumption that if the envelope contains any useful 
information (digital signatures, transaction control, information in the 
body) other than a signal that a GET is being done, then the operation is 
presumed unsafe, in which case POST is used.  Also: here we deal with 
non-RPC SOAP requests; RPC is discussed below.

This proposal therefore provides that there is exactly one form of a SOAP 
request that will result in an HTTP GET.  It looks like this:

<soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope>
        <soap:Body>
                <REST:GET 
xmlns:REST="http://www.fieldingsthesis.org/rest4soap"/>
        </soap:Body>
</soap:Envelope

Let's call this the "magical restful GET request".  It must appear exactly 
as shown, with no additional body information, and no SOAP headers.  It is 
an error to use the REST:GET element in any other context (if you study 
the SOAP feature architecture, you'll find that it gives you away to 
loosen this restriction in a controlled way later [4]). 

To retrieve information in a RESTful manner, a SOAP node sends the magical 
get request envelope to the resource in question.  Here's where the 
infoset trick comes in.  >>> The HTTP binding represents that envelope as 
an HTTP GET, with no body.<<  The current HTTP binding uses POST of the 
XML 1.0 serializations of the envelope infoset.  The "improved" binding 
would say:

* The magical restful GET request is represented as an HTTP GET, with no 
body. 
* All other envelopes are transmitted as POST, using XML 1.0 serialization 
(I.e. as today)

Receipt of an HTTP GET is a signal to the receiving node that the envelope 
transmitted was in fact the magical get request envelope.  That envelope 
is therefore processed per the normal SOAP processing rules [5].  The 
semantics of the REST:GET element at the receiver are:  retrieve a 
representation of the resource to which the request was sent.  That will 
result in an SOAP HTTP response with the (representation of) the request 
resource.  That representation SHOULD be a SOAP document (typically 
application/xml+soap).

Some characteristics of this proposal
-------------------------------------

* It applies REST:GET in a uniform way across multiple underlying 
protocols.  The HTTP to MQSeries example above can in principle be 
supported.

* It correctly separates the identification of the resource (the URI, 
about which we need say nothing) from the operation (GET).

* It correctly labels the operation as a RESTful get, and not some other 
vaguely safe operation.

* It is appropriately conservative in presuming that any additional in the 
information in the envelope might represent loss of safety. 

* By representing the request as a SOAP envelope, we allow receiving nodes 
to apply the full SOAP processing model, albeit to a very stylized 
request.

* It's relatively simple.

What about RPC?
---------------

I believe the REST community is correct that the famous getStockQuote 
example is not RESTful. 

        stockprice = getStockQuote("ibm","1/1/2002)

We can do this RPC in a restful way by applying something similar to Tim 
Bray's trick [6] >> at the endpoint << and sending the magical RESTful get 
to retrieve the information.  So, the URI would look like: 

        http://www.stockprices.com/prices?company="ibm"+date="1/1/2002"

The body would be as above, and the binding would turn it into a vanilla 
HTTP GET.

What makes this proposal different from Tim's is that we don't start with 
a SOAP RPC envelope.  The mapping of method arguments into the URI is 
purely the business of the endpoints...the company name and date never 
exist in a SOAP body.  One way to do this would be with a WSDL convention: 
 mark the parameters that identify the resource.  The endpoint then knows 
to map them to the URI.  I'm not 100 percent sure this is a good proposal, 
but I think it's worth considering.

Now, what's more complicated is maintaining symmetry in the following 
cases:

        bal = getBankBalance(NoahsAccount);
        updateBankBalance(NoahsAccount, "10000000.00");

The getBankBalance would be handled exactly as for getStockQuote above. 

        URI:  http://www.megabank.com/accounts?accountname="NoahsAccount"
        SOAP Envelope:  magical get request
        HTTP operation: GET
        HTTP body:  none

The WSDL-based description of the RPC for update would have to distinguish 
parameters used to identify the resource, from those to be included in the 
operation on wire.  In this case, NoahsAccount identifies the resource, 
and the 10000000.00 second parameter is actually sent in the RPC in the SOAP body.  Once 
again, this is correct REST, I believe.

        URI:  http://www.megabank.com/accounts?accountname="NoahsAccount"
        SOAP Envelope:  SOAP 1.2 RPC for updateBankBalance (not sure if we 
send only
                        2nd parm or both)
        HTTP operation: POST
        HTTP body:  XML 1.0 serialization of the Envelope.

Conclusions
-----------

I'm not convinced this proposal is a good one.  If nothing else, I hope it 
goes some way toward highlighting where the issues and opportunities are. 

I believe this shows that SOAP is not deeply broken, but that modest work 
can get us where we need to be.  There is, of course, the question of 
whether a capability like this should be in the initial SOAP 1.2 
recommendation.  The advantage would be having a normative, interoperable 
way of doing GET on day 1.  On the other hand, nothing in the 
recommendation will break if someone publishes an updated binding a little 
later.  The risk would be that early implementations would not understand 
the GET idiom as representing a true SOAP request.  I personally am more 
or less neutral as to whether it goes in the REC or not, but I wouldn't 
mind (presuming the proposal holds up).

Also:  I think it's worth pointing out that the added capabilities in SOAP 
(vs. HTTP)  are not gratuitous.  The reason for structured headers and the 
associated processing model is that many requests will be end-to-end 
signed, authenticated, transaction controlled etc.  I am not an HTTP 
expert, but I suspect that an information retrieval request accompanied by 
such higher level controls is rightfully a POST (I.e. not safe), at least 
in many cases.  The feature architecture of SOAP would allow us to later 
identify specific situations in which an authenticated GET (for example) 
could indeed map to a RESTful retrieval.

Again, apologies for the long note.  I hope this is useful.

Noah

[1] http://www.w3.org/2000/xp/Group/2/04/11/soap12-part1-1.86.html
[2] http://www.w3.org/2000/xp/Group/2/04/11/soap12-part2-1.55.html
[3] 
http://www.w3.org/2000/xp/Group/2/04/11/soap12-part1-1.86.html#transpbindframew
[4] 
http://www.w3.org/2000/xp/Group/2/04/11/soap12-part1-1.86.html#extensibility
[5] http://www.w3.org/2000/xp/Group/2/04/11/soap12-part1-1.86.html#msgexchngmdl
[6] http://lists.w3.org/Archives/Public/www-tag/2002Apr/0211.html

------------------------------------------------------------------
Noah Mendelsohn                              Voice: 1-617-693-4036
IBM Corporation                                Fax: 1-617-693-8676
One Rogers Street
Cambridge, MA 02142
------------------------------------------------------------------

Received on Wednesday, 24 April 2002 12:47:20 UTC