Sunday, September 1, 2013

RESTful - to PUT or to POST

This is an effort to simplify your decision making.

Reference

http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

PUT

1. If the resource created/modified is represented by the URI

http://myservice.com/users/xyz

The body should contain data about xyz. If xyz is not found it is created else updated. Based on this
201, 200 or 204 is returned. In PUT the call is handles by the resource.

If the resource could not be created or modified with the Request-URI, an appropriate error response SHOULD be given that reflects the nature of the problem.

POST

1. If the resource created/modified is NOT represented by the URI

http://myservice.com/registration

The body should contain data about registration (the form filled). It may create multiple resources, account, user, address. It might as well create a single resource. The POST call goes to the handler than directly to the resource.

Why should we worry about these verbs?

It helps the user agent. You can even perform an update during a GET call and no one would stop. But the client might not be aware of it.

GET is a safe method and is allowed for caching.
PUT is an idempotent call, N > 0 same request would have same effect as one request.

e.g.

> http://myservice.com/comments

Ideally you would design this as POST and multiple call to it would create multiple posts.

> http://myservice.com/comments/1234

This would be called with PUT, assuming POST was called earlier (of course you not create comments passing the ID in URL using PUT). N same calls with same content would result the comment in same state.

The fundamental difference between the POST and PUT requests is reflected in the different meaning of the Request-URI. The URI in a POST request identifies the resource that will handle the enclosed entity. That resource might be a data-accepting process, a gateway to some other protocol, or a separate entity that accepts annotations. In contrast, the URI in a PUT request identifies the entity enclosed with the request -- the user agent knows what URI is intended and the server MUST NOT attempt to apply the request to some other resource. If the server desires that the request be applied to a different URI, it MUST send a 301 (Moved Permanently) response; the user agent MAY then make its own decision regarding whether or not to redirect the request.

A PUT says to not update any other resource than that in the request URI but entry in a ledger file can be ignored.

There are scenarios where response to POST can be cached but never response to PUT.

So what should be taken care is the expectation of the user agent. None of these things dictate what is done on the server side.

Another example, if I have a class User


@Path("/posts/")
Class Post {

@PUT
@PATH(/<postId>/)
createOrUpdate() {}

@POST
@PATH(/comments/)
createComments() {}

@POST
@PATH(/tags/)
createTags() {}

}

@Path("/comments/")
Class Comment {

@PUT
 @PATH(/<id>/)
 createOrUpdate() {}
}

HTH

If you have read so far and have to add. Please do so.

1 comment:

Amod Pandey said...

Off the track note. Suppose there is a collection parameter. How to sent such parameter from

@QueryParam("users") final Set users

http://myservice.com?users=amod&users=alok

This will populate the set with amod and alok.