- 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