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