Simon
Fell: Sam has updated his comment API to support a preview
mode. Whilst I normally agree with what Sam writes regarding Web
Services, this one just doesn't sit right with me, it smells very
RPCish going against Sams own messaging message. It seems to me,
that it ought to be that you send the same message to a different
URI to do preview, not tag in a SOAP header.
Be careful when you attempt to label me. ;-)
When given a choice between options A, B, and C, I generally
reply YES, and then proceed to do exactly that.
But let's explore this one a bit further. It tickles me to
no end that the first
message
I received from somebody other than myself was from
Radio. If you were to personify that software, I'm sure you
would agree that it 'thought' it was sending an RPC request.
These two worlds are not as far apart as they seem.
What I don't like are brittle, tightly coupled interfaces.
If you were to look at existing usage, the correlation between such
interfaces and RPC is much higher than with messages, so I'll
accept that a relatively good first order approximation is that
messaging is better than RPC. But in my book, that's not the
whole story.
Now let's explore the option of supporting a different
URI. The first obvious choice is to append something like
"?preview=yes" to the URI. This smells RPCish to me, but that's
OK. What's wrong with this is that the typical CGI will treat
it as an optional parameter, and if they weren't looking for it,
they would ignore it.
Anyway, if we can come to agreement on how to do this safely
with another URI, then I will simply support that option too.
Fair enough?
RPCish
Sam responds to my earlier comment on the preview API. At some level all the choices smell RPCish to me, this is about the point I get stuck on the whole RPC/REST/Messaging discussion, why is any of these magically better than the others, they all ...
This has several benefits, one is that you can tell, by the existence of the 'wfw:preview' element, if the service supports previews. In your proposal the only way to find out is by trying, and potentially failing.
Also avoids 'unexpected' results. If someone trys to 'preview' a post and the server ignores the must-understand flag and creates the comment. [Unfortunately this is what will happen with my current implementation of the CommentAPI]
Third, it allows for re-use. I could create a single web service endpoint that does previews, for both Comments and RESTLog item POSTs.
As for appending "?preview=yes", I wouldn't want to make the specification require a specific form of the URL. I do that a little with the RESTLog API now, and even that little bit I am considering removing from the spec:
2 is better than 3 as one can put a mustUnderstand attribute on the header. Besides, a soap body probably should only have one nested element (I don't mean to debate that here and now, just mentioning it passing).
Both 1 and 2 are workable, IMHO - as long as the URL is treated as opaque. I agree with Joe, I would much prefer the actual syntax of the URL not be specified.
Joe, we are now up to two services, and you are now suggesting that we double the number of wfw elements in the RSS. Do you expect this trend to continue? Remember, that these are elements that will appear on each item.
Alternatives worth exploring: having a single element that points to a descriptor (WSDL?) of all of the services provided. This could even be WSIL style where the abstract description is separated from the binding.
Another alternative would be having a single declaration of what services are supported in the channel element.
P.S. The idea of having multiple URI's map to a single resource seems curiously inconsistent with Roy Fielding's original REST thesis.
From my understandings of the RESTifarian religion Simon and Joe are right. It would seem to be consistent with Fieldings thesis that one would send the same message to different URIs to perform different actions instead of having a tag in the message control the action if one wanted to be truly RESTful.
However since REST is at best are a set of guidelines I think practical considerations should also play a part in the decision making process. As one of the few people who's actually writing a client for this API, I probably would prefer sending an extra element in the message than dicking around with WSDL and WSIL.
Then again my time is scarce so I tend to go for the quick and easy solutions.
Dare: have you read Roy's thesis? I have. A URI is intended to identify a resource. Also read the definition of POST.
Don't worry too much about WSDL and WSIL at this point. My intent is to only require as much as is absolutely necessary, and yet be consistent as possible with the widest range of existing standards and tooling.
As you have already seen, you can post a comment without any knowledge of WSDL. Yet I also posted a WSDL and a C# client which makes use of this. Use whatever you find appropriate, I don't care.
Sam,
I've read Roy's thesis. I've also observed and participated in email threads spanning weeks and hundreds of messages on the W3C Technical Architecture Group mailing list about URIs and resources. Eventually most of us came to the conclusion that the only the various specs definitively say is that
"A URI is something that identifies a resource"
"A resource is something identified by a resource"
Everything else has been layered upon by opinion, practice and blind faith. So when you say "a URI is supposed to identify a resource" you need to clarify what is meant by a resource in your world view and also why you think multiple URIs can't identify the same resource (do http://www.25hoursaday.com and http://25hoursaday.com identify different resources
Mapping this to another domain for clarity. A typical word processor has print and print-preview menu items. These are itended to operate on the current document. I don't believe that the correct mapping of such a design to REST would involve separate multiple URIs for the same document.
I'm trying real hard to be nice here. I see in what can only be described as the canonical example of REST, head and even meta tags. That's why I find it very frustrating when I am told to avoid such things when designing an API.
Let's figure out what makes sense, reuse where we can, and only reinvent when we must.
Sam,
Using your analogy I'd say that the Word Processor is the resource which has URIs identifying various aspects of it such as printing and print preview. While the document is unchanging regardless of whether you are printing it or checking the print preview.
I'm just playing devil's advocate. Personally I think you should do what is most convenient for yourself and your users instead of blindly trying to follow a methodology. Almost all software development rules are just guidelines not hard and fast rules. It's up to us to decide when the guidelines do not apply to our scenario and modify the rules to fit the situation.
If the word processor was the resource, it would be identified uniformly with a single identifier. That one identifier would be a URI.
A document centric view would be prefered by most. On URI per document.
Making multiple URIs onto one resource is common practice. My various RSS feeds and HTML are representations of a single resource.
What I question is the characterization that the reason to do this is to make the system MORE RESTful. To me, that misrepresents that architectural ideals that Roy Fielding espouses.
re: devil's advocate... please do. Just please be more specific than 'smells' and 'soap processing model', ok? If you see anything missing from this, let me know.
Each of you (Joe, Dare, Simon) are writing clients. What's easiest for each of you?
I can handle all 3 cases with fairly equal ease. as already discussed 1 has the added overhead of having to discover the uri. 2 & 3 have an overhead of discovering if its supported.
Simon: thanks. I guess my preference is to add a single element to the channel per feature instead of adding it to each item. I think that addresses the discovery question for options 2 and 3. Would you agree?
When you say you can handle all three with equal ease, is that from a RelaXer or a Pocket Soap perspective, or both? Do you have a preference?
Sam,
I can answer one small part of what is easiest. On the client-side, if there are two seperate URLs, wfw:comment and wfw:preview, then I can use the existence of wfw:preview to enable or disable the "Preview" button on the UI.
On the server-side implementation, I can also answer that it would be easier if they were seperate URLs, mostly because I do the transformation being previewed very late. That is, I keep the original text that the poster submitted and transform it with your 'sanitize()' function when I rebuild a page. That way any enhancements to the 'sanitize()' function will affect all comments no matter when they were posted. Because of that, I don't go anywhere near 'sanitize()' when accepting a comment, only when rebuilding files. That is, the comment posting code will have larger differences from the preview code than you might have thought. [Some of that may change if I implement previewing for comments submitted via the web form.]
Yes, a channel level element in RSS sounds good to me.
It would be easy enough to do with PocketSOAP, however the windows version of relaxer uses .NET, so i'd probably just use built in SOAP support. I don't know how far i'll take relaXer (the OSX version), Cocoa's XML support seems to consist entirely of a DOM implementation, and the SOAP support is twisted horibly into AppleScript/Events.
Rest is about resources. Resources the server has and the client wants to get, add to or change.
A preview is none of these things. It's a server-side transformation of input from the client. A tranformation of input, returning output; the definition of a function (without side-effects). That's why this all feels so RPCish. It is RPC, no matter what technology you use.
The only resource on the server here is the transformation. The only way I can think of to do this that doesn't smell RPCish is to GET the transformation itself. (which could be an XSL file f.e.) Then the client can perform the transformation.
I don't think this is a very helpful solution, so let's just smell RPCish. It's not that bad a smell anyway.
Sjoerd: I think you 'grok' REST more than many of the supposed REST cheerleaders do.
REST is about managing state. The fact that there is no implicit state shared between the client and the server, and that all the state information required to process the request is available as a part of this request, makes this particular RPC call compliant with REST.
Yes, I'll say it again: this interaction is both RPC and REST.
Furthermore, there is nothing in REST which says that a HTTP header should be used instead of putting data in a body. Nor is there anything in REST which says that multiple resources are the proper way to model this interaction (actually, to the contrary: it is one resource).
- - -
Just curious... has anybody noticed that the HTML form which is used to create comments on my weblog entries utilizes POST, and sends the data to a single URL? So does MT-comments for that matter. And in both cases, it is some data in the body which defines the difference between the two.
Well, I have of course, having built several HTML comment forms with preview, but I wasn't sure whether that applied to this philosophical discussion.
The one thing I need is to know that my preview request cannot possibly ever be treated as a submission. That's something I've always handled by requiring that the POST tell me what it wants: whether it's by saying "request=(post|preview)" or "preview=true|post=true", if a form doesn't tell me what to do I won't do anything. I can't imagine being willing to preview in a situation where the difference was that a preview was exactly the same request with something added. Exactly the same request sent to a different URI, fine, exactly the same request with something changed, fine, I've got no religious preference, but the only way that I would be willing to use preview that worked by adding a SOAP header would be if SOAP was required, rather than optional. If the SOAP wrapper is optional, and the only difference between preview and submit is an optional header in the optional SOAP, then dirty people who hate SOAP will implement it in a way that treats a SOAP preview as a non-SOAP submit, and that means I'm afraid to implement it at all. I vote for either a separate URL, or a required wfw:request element in the body saying what you want done with it.
Take a step back. Look at the overall flow. With HTML, you first download a form. The recipient understands the form. Based on the instructions it finds therein, it sends a properly formatted POST. This POST encodes the request in the body. Perfectly RESTful.
Now let's take a look at a web services equivalent. First, you download a WSDL. The recipient understands the WSDL. Based on the instructions it finds therein, it sends a properly formatted POST. This POST encodes the request in the body. Perfectly RESTful.
This can be improved. If we can agree in advance on the format of the data, we can dispense with the first request. However, we need to wrap the item in something as XML only permits one documentElement per document. Like HTML, SOAP simply defines an outer envelope with a Head and a Body.
Now let me caution you on one thing. I realize that there is a temptation to say that <wfw:request> is clearly required and is the one and only thing we will ever, ever, ever need. Unfortunately, forever is a long time. What we need is a standard way to be able to add elements that can be ignored. And elements which can not be ignored.
That, in a nutshell, is pretty much all SOAP is. It doesn't take much code to implement. Unfortunately there has been a massive campaign to discredit these relatively simple ideas that some people simply stop listening when SOAP is mentioned.
It is my hope that we can work together and find a middle ground. The middle ground I see is as follows:
in situations where headers are not required, the envelope is optional. If a server receives a request without an envelope, the server MUST respond in kind.
in situations where headers are required, we don't invent new elements, we reuse the ones already defined. Furthermore, if headers are sent, we check to see if they are marked mustUnderstand and respect this. Finally, if a request is received with such an envelope, the server MUST respond in kind.
To me, this seems like a reasonable compromise. What do others think?