- From: <noah_mendelsohn@us.ibm.com>
- Date: Wed, 24 Apr 2002 12:30:44 -0400
- To: www-tag@w3.org
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