I have seen many programmers having confusion between PUT vs POST while making REST API. Before starting my article let me put the following statements you have already encountered with:
If you are following these statements sctrictly, both of them are not correct!. It is not mandatory that you have to use both PUT and POST in our application, it depends on what is the requirement. If you want to use "POST" you must have a reason why you opted for "POST" and not "PUT" and a similar question arises while using "PUT". You have to ask yourself which is the best method for your particular requirement. To decide whether to use "PUT" or "POST" you need to understand idempotent operation. Let's go through on Idempotent operation in brief:
It means no matter how many times you call the operation the result/output will be the same. Of the major HTTP verbs, GET, PUT, and DELETE are idempotent (if implemented according to the standard), but POST is not. This means how many times you call "GET", "PUT" and "DELETE" with same input conditions (ie. same url , same input data) the end result (output) is the same. For pure functions then idempotency signifies that f(x) = f(f(x)) = f(f(f(x))) ....for all the values of x. PUT, being Idempotent, means putting a resource i.e completely replacing whatever is available at the given URL with input provided. It is a kind of setting a variable with some value i.e (x=5) how many times you do x=5 it will always be same. POST signifies adding a subsidiary resource to a particular resource, i.e. it updates a resource. For example x++ is a kind of POST operation it will increment x everytime you call it. It is not idempotent.Getting back to difference between PUT and POST:PUT can be used on a resource whether that resource previously exists or not. You can use that on both Create or Update. POST can be used to add new things to specified resource. Consider you are having a books web application and here is the way to access it:
We will discuss the four different cases below with reference to above example:
Lets say you have to create a new book at following resource "http://blahblablahblah.com/books" you will use :
POST /books HTTP/1.1Host: wahteverblahblah.com
In POST data you will send the required data to create a book like book name, book description, book price. Note you are not providing bookid here and are making server decide what will be the bookid. You are posting a book to book collection (http://blahblablahblah.com/books). In my opinion whenever you have to add a resource to a collection and let the server decided what will be the GET url for that resource (say http://blahblablahblah.com/books/2), use POST. This is not idempotent, whenever you call the above operation a new book will be created with new bookid. If you try to call this operation instead:
POST /books/<new_book_id> HTTP/1.1Host: blahblablahblah.com
The above operation will not work and will throw "Resource not found" error and the reason for this is that the book with new_book_id has not been created yet. The POST operation defination says that it is done on existing resource so the "POST /books/<new_book_id>" operation will create an error. If the URL has not been created yet, you should not use POST to create it while specyfing the name You should PUT the resource on the server first in this case.
Alright, since we used POST (Updates a resource, adds a subsidiary resource.) for creating a resource in the above example (POST /books HTTP/1.1), one important thing to consider above is that it is used to create a subsidiary resource and not just to create a resource i.e we added the resource to a callection "http://blahblablahblah.com/books" that is why it is a subsidiary resource. If you want to use "/books/<new_book_id>" as the create url you have to use PUT.
POST - Modifying a resource (Partial Updates)
Let's say you want to update the bookname of bookid 1. You will go like this:
POST /books/1 HTTP/1.1Host: blahblablahblah.com
You will send "bookname" as post data to modify the bookname at following resource "http://blahblablahblah.com/books/1". Note in this case we are just updating name of the book and nothing else so this is a kind of partial update. If you want to replace the resource completely go with PUT else with POST.
If you want something to be created a specified url i.e the location via which you can GET the resource too use PUT. You will do the operation like this:
PUT /books/1 HTTP/1.1Host: blahblablahblah.com
Above operation will create a new book with book id 1 at the following location http://blahblablahblah.com/books/1. On this case the client is deciding what will be the id of new book.
PUT - Modifying a resource
If you want to completely replace a resource with something you should use PUT. You will do the operation like this:
PUT /books/1 HTTP/1.1Host: blahblablahblah.comAbove operation will completely replace the book with book id 1 at the following location http://blahblablahblah.com/books/1 with the input data provided. Yowu might be wondering that for creating as well as modifying a book with bookid 1 we are using the similar operation:POST /books/1 HTTP/1.1Host: blahblablahblah.comSo wherer is the difference? Here comes the magic of PUT. With this operation "PUT /books/1 HTTP/1.1" PUT is asking the server if a resource exists at the location "http://blahblablahblah.com/books/1" just modify it with whatever input data is present and if it doesn't exists, create a new resource at the following location http://blahblablahblah.com/books/1 . That is why PUT is Idempotent. If the resource exists it will modify it and if the resource doesn't exists it will create it. So no matter how many times you call it you will have only one resource.
According to http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5
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. 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.
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.The action performed by the POST method might not result in a resource that can be identified by a URI. In this case, either 200 (OK) or 204 (No Content) is the appropriate response status, depending on whether or not the response includes an entity that describes the result.If a resource has been created on the origin server, the response SHOULD be 201 (Created).
PUT is an idempotent operation, POST isn’t. So if I pass in an object that the server is supposed to find a unique ID for and add to a parent object, that’s a POST. If you invoke that method times you’ll create new objects as children of the parent. If I update (or create) an object by passing in a _complete_ copy of it, that’s a PUT.