Please don't call it a REST API, when it is clearly an RPC API. It's confusing.
You would want to focus on noun based resource access for loosely
coupled systems (ie: one server supplying many clients).
The RPC stuff calling actions, running methods etc, seems to me to be
more tightly coupled (ie: the methods are accessible directly through
the URL, that's about as tightly coupled as it can get) better
optimized for 1-1 web services or private/secure network
communication.
Ideally, SilverStripe would provide the basic tools and patterns that
enable apps to use either paradigm, I don't think it's necessary to
take a hardline RESTful stance - however, I do think it's good you
recognize that REST is a good approach to use building websites in
general, and encourage this with the basic data access patterns.
However, RPC might be an easier and more pragmatic approach for
certain use cases. The main issue I would say is the tight coupling,
but again, this might be ok for many scenarios, where a pure model
would be more opaque and subtle. The RPC way just allows you to tweak
parameters and slam the API directly with very little abstract
thinking required.
Or to rephrase my last email: once the cat is out of the bag (ie: a
data object RPC API is in the wild), people will start using it, and
it's going to be much harder down the line to rearchitect it in a
RESTful style, if we ever figure out how to resolve the problems with
natural "verb actions" you mention, like publish, etc.
In general, you should be using the HTTP status codes to signal the
result of an operation.
Creating a new object should return a 201 if the request succeeded.
Ideally, the response body would provide a URI that you could then GET
to see the new object. Opinions may vary, but I don't see anything
wrong with also returning the main fields of the object data in this
response too.
Use status code 202 to indicate that a request has been accepted by
the server, but may not necessarily be able to return a result
immediately. For example, if you triggered a method to clear a cache
or do a whole bunch of ongoing changes out of band that take too long
to just tell you the response immediately. 202 means your client now
knows that the operation is "in progress", again, it needs to check
back with a GET on whatever status URI to confirm the changed state.
This is the achilles heel of HTTP - there's no way for the server to
"ping" back to the client to tell you that it has finished what you
asked it to do.
(do a google search for "http comet" to find one particular workaround
for this).
The tricky thing is in the details, ie: *what does it mean for an
operation to succeed or fail*... This is internal to your app, it
can't be answered at the protocol level.
RPC architectures have a similar mismatch to the ORM impedance
mismatch between objects and databases. That is, with setter methods
that update an object state, local method calls often return void, and
throw an exception if the method fails.
But across a network with messages, you can't really fire a request
into the void, and not get any answer.
But getting back to the question of what it means to succeed or fail,
this could be different, depending on what the method call is, and all
the side effects that it has on the system. Maybe it is just updating
the state of a single object, but maybe it's actually touching a whole
bunch of other things. There isn't a general case, you have to look at
the specific method and what it is doing.
Hope that makes some kind of sense.
POST /SiteTree/Live
<Page PageID="3" />
To unpublish:
POST /SiteTree/Draft
<Page ID="3" />
GET /SiteTree/Live
<SiteTree PublicationStatus="Live">
<Page ID="3" When="2009-01-01" />
<Page ID="4" When="2009-01-02" />
</SiteTree>
GET /SiteTree/Live/Changes
<Changes PublicationStatus="Live">
<Publication ID="3" When="2009-01-01" />
<Removal ID="3" When="2009-01-04" />
</Changes>
Or for an individual page:
GET /SiteTree/3/Changes
<Changes ID="3" PublicationStatus="Draft">
<Publication When="2009-01-01" />
> Still, you're unlikely to be able to hook this into some 3rd party
> tool without specifically designing it for SilverStripe, which kind of
> defeats the purpose a little.
If that is the intent, then it's best to go with the Atom Publishing
Protocol, since that's the only standard of this type that seems to
have widely available tools... the alternatives are even more esoteric
than the ideas being discussed in this thread.
http://www.ibm.com/developerworks/library/x-atompp1/
eg: it's natively supported by browsers like Flock, and I think
Windows Live Writer does it as well.
> Sig: seems a bit OTT. Usually if you are using a REST API you already
> know the classes. What would the benefit be? APIs are usually a bit
> useless without documentation anyway
This would help towards self-documentation, provides help in debugging
situations, leads to discovery of new ways to use the data, especially
if the API is public.
Sigurd
http://www.oracle.com/technology/tech/feeds/spec/draft-divilly-atompub-hierarchy-00.html
I would assume that draft/published would just be treated as separate
collections.
This http://code.google.com/apis/gdata/ is also an extension of the
APP I believe.
http://atomenabled.org/developers/protocol/#appDraft
Turns out this is represented by a draft element on the entry itself.
The draft/live collections would just be a 'nice to have' feature, if
you wanted to expose the queries/lists to clients.