On 7/1/2013 9:47 AM, Ade Lee wrote:
The REST guidelines are precisely that - guidelines - and we can
choose
to ignore them at our discretion. But there are distinct advantages to
following them. In particular, when doing so, anyone looking at the API
knows exactly what is going on. By using PUT, its clear that the client
is responsible for providing the resource ID.
REST basically says to use the HTTP spec to determine what operation to
use. To see what the REST guideline would be in this case, lets see
what the HTTP spec says about PUT:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.6
The PUT method requests that the enclosed entity be stored under the
supplied Request-URI. If the Request-URI refers to an already existing
resource, the enclosed entity SHOULD be considered as a modified version
of the one residing on the origin server. If the Request-URI does not
point to an existing resource, and that URI is capable of being defined
as a new resource by the requesting user agent, the origin server can
create the resource with that URI. If a new resource is created, the
origin server MUST inform the user agent via the 201 (Created) response.
If an existing resource is modified, either the 200 (OK) or 204 (No
Content) response codes SHOULD be sent to indicate successful completion
of the request.
This defines what PUT does, but it doesn't necessarily require us to use
PUT if we know the resource ID already. The POST is equally valid:
From
http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5:
The POST method is used to request that the origin server accept the
entity enclosed in the request as a new subordinate of the resource
identified by the Request-URI in the Request-Line. POST is designed
to allow a uniform method to cover the following functions:
- Annotation of existing resources;
- Posting a message to a bulletin board, newsgroup, mailing list,
or similar group of articles;
- Providing a block of data, such as the result of submitting a
form, to a data-handling process;
- Extending a database through an append operation.
The actual function performed by the POST method is determined by the
server and is usually dependent on the Request-URI. The posted entity
is subordinate to that URI in the same way that a file is subordinate
to a directory containing it, a news article is subordinate to a
newsgroup to which it is posted, or a record is subordinate to a
database.
Adding a new user or profile into a collection would be analogous to the
above examples.
On 7/1/2013 9:47 AM, Ade Lee wrote:
The point you make about possibly overwriting an existing resource
is
valid -- but the answer there is etags. And as e will be writing the
first clients for this, we can safely say that - yes - all clients will
support etags.
With REST anybody can write their own client or use generic tools to
access our interface. Of course the client must provide the required
parameters in all requests, but if we require clients to use what
supposed to be optional in REST we will reduce the number of clients
that can use the interface.
REST provides two different -- but valid -- mechanisms: PUT and POST. I
think there are enough reasons to use separate operations for create and
update:
* Different behavior: create should fail if entry already exists where
as update should fail if entry doesn't exist.
* Different security: not all users are allowed to create an entry.
* Server won't need to check if entry already exists.
* If operation fails because entry exists/doesn't exist the client will
know it.
* Client won't need to determine which URL to use.
* It works without ETag. Client won't need to do an extra GET operation.
* Client can still use ETag if concurrency is a concern.
Here's what Bill Burke said when we discussed about this when we're
discussing the users interface:
On 5/24/2012 11:33 AM, Bill Burke wrote:
> 1. Considering all the requirements, should CREATE and UPDATE be
> handled by a single or separate methods?
Because you only want admins to be able to create a user, and non-admins
can update users, you should probably use the @Post method to create,
and not use @Put for creation.
@POST @Path("/users") create();
for
@PUT @Path("/users/{id}") update(); you should throw a 404 if the user
doesn't exist.
> Suppose the security requirements are the same for both
operations,
> would you design it differently?
All depends whether or not I wanted to rely on the client to pick the
URI or not. I usually use the @POST /users because it gives the server
a lot of flexibility on what the returned URI (in the Location header)
looks like.
On 7/1/2013 9:47 AM, Ade Lee wrote:
Just because we may not implement etags in the first iteration does
not
mean that we should use non-standard API in our design.
Using POST won't be non-standard, but requiring ETag for this to work
might be. Here's what Bill said:
> 3. Is it OK to require the use of ETag to distinguish CREATE and
UPDATE
> (requiring a GET operation before every UPDATE)? Or should ETag be
> optional and used only if the system requires caching or concurrency
> control?
It is never OK to override the meaning of a header, HTTP method, or
response code. One of the nice things about REST is that you have a
solid foundation of how a service behaves without ever looking at the
documentation of that service: This is because you know the HTTP protocol.
ETag should only be used for conditional GET (when a cache is involved)
or a conditional PUT, or POST (When concurrency is involved).
To me this means if someone installs a system and there's only one
client using it, or any other situation where concurrency is not an
issue, he shouldn't be required to use ETag.
--
Endi S. Dewata