PUT vs. POST in REST
According to the HTTP/1.1 Spec:
POSTmethod 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
In other words,
POST is used to create.
PUTmethod requests that the enclosed entity be stored under the supplied
Request-URI. If the
Request-URIrefers 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-URIdoes 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."
PUT is used to create or replace.
So, which one should be used to create a resource? Or one needs to support both?
Both PUT and POST can be used for creating.
You have to ask "what are you performing the action to?" to distinguish what you should be using. Let's assume you're designing an API for asking questions. If you want to use POST then you would do that to a list of questions. If you want to use PUT then you would do that to a particular question.
Great both can be used, so which one should I use in my RESTful design:
You do not need to support both PUT and POST.
Which is used is left up to you. But just remember to use the right one depending on what object you are referencing in the request.
- Do you name your URL objects you create explicitly, or let the server decide? If you name them then use PUT. If you let the server decide then use POST.
- PUT is idempotent, so if you PUT an object twice, it has no effect. This is a nice property, so I would use PUT when possible.
- You can update or create a resource with PUT with the same object URL
- With POST you can have 2 requests coming in at the same time making modifications to a URL, and they may update different parts of the object.
Used to modify and update a resource
POST /questions/<existing_question> HTTP/1.1 Host: www.example.com/
Note that the following is an error:
POST /questions/<new_question> HTTP/1.1 Host: www.example.com/
If the URL is not yet created, you should not be using POST to create it while specifying the name. This should result in a 'resource not found' error because
<new_question>does not exist yet. You should PUT the
<new_question>resource on the server first.
You could though do something like this to create a resources using POST:
POST /questions HTTP/1.1 Host: www.example.com/
Note that in this case the resource name is not specified, the new objects URL path would be returned to you.
Used to create a resource, or overwrite it. While you specify the resources new URL.
For a new resource:
PUT /questions/<new_question> HTTP/1.1 Host: www.example.com/
To overwrite an existing resource:
PUT /questions/<existing_question> HTTP/1.1 Host: www.example.com/
Additionally, and a bit more concisely, RFC 7231 Section 4.3.4 PUT states (emphasis added),
The PUT method requests that the state of the target resource be
replacedwith the state defined by the representation enclosed in the request message payload.
Read more... Read less...
You can find assertions on the web that say
- POST should be used to create a resource, and PUT should be used to modify one
- PUT should be used to create a resource, and POST should be used to modify one
Neither is quite right.
Better is to choose between PUT and POST based on idempotence of the action.
PUT implies putting a resource - completely replacing whatever is available at the given URL with a different thing. By definition, a PUT is idempotent. Do it as many times as you like, and the result is the same.
x=5 is idempotent. You can PUT a resource whether it previously exists, or not (eg, to Create, or to Update)!
POST updates a resource, adds a subsidiary resource, or causes a change. A POST is not idempotent, in the way that
x++ is not idempotent.
By this argument, PUT is for creating when you know the URL of the thing you will create. POST can be used to create when you know the URL of the "factory" or manager for the category of things you want to create.
- POST to a URL creates a child resource at a server defined URL.
- PUT to a URL creates/replaces the resource in its entirety at the client defined URL.
- PATCH to a URL updates part of the resource at that client defined URL.
The relevant specification for PUT and POST is RFC 2616 §9.5ff.
POST creates a child resource, so POST to
/items creates a resources that lives under the
/items/1. Sending the same post packet twice will create two resources.
PUT is for creating or replacing a resource at a URL known by the client.
Therefore: PUT is only a candidate for CREATE where the client already knows the url before the resource is created. Eg.
/blogs/nigel/entry/when_to_use_post_vs_put as the title is used as the resource key
PUT replaces the resource at the known url if it already exists, so sending the same request twice has no effect. In other words, calls to PUT are idempotent.
The RFC reads like this:
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,
Note: PUT has mostly been used to update resources (by replacing them in their entireties), but recently there is movement towards using PATCH for updating existing resources, as PUT specifies that it replaces the whole resource. RFC 5789.
Update 2018: There is a case that can be made to avoid PUT. See "REST without PUT"
With “REST without PUT” technique, the idea is that consumers are forced to post new 'nounified' request resources. As discussed earlier, changing a customer’s mailing address is a POST to a new “ChangeOfAddress” resource, not a PUT of a “Customer” resource with a different mailing address field value.
This forces the API to avoid state transition problems with multiple clients updating a single resource, and matches more nicely with event sourcing and CQRS. When the work is done asynchronously, POSTing the transformation and waiting for it to be applied seems appropriate.
Can be performed with both PUT or POST in the following way:
Creates THE new resource with newResourceId as the identifier, under the /resources URI, or collection.
PUT /resources/<newResourceId> HTTP/1.1
Creates A new resource under the /resources URI, or collection. Usually the identifier is returned by the server.
POST /resources HTTP/1.1
Can only be performed with PUT in the following way:
Updates the resource with existingResourceId as the identifier, under the /resources URI, or collection.
PUT /resources/<existingResourceId> HTTP/1.1
When dealing with REST and URI as general, you have generic on the left and specific on the right. The generics are usually called collections and the more specific items can be called resource. Note that a resource can contain a collection.
<-- generic -- specific -->
URI: website.com/users/john website.com - whole site users - collection of users john - item of the collection, or a resource URI:website.com/users/john/posts/23 website.com - whole site users - collection of users john - item of the collection, or a resource posts - collection of posts from john 23 - post from john with identifier 23, also a resource
When you use POST you are always refering to a collection, so whenever you say:
POST /users HTTP/1.1
you are posting a new user to the users collection.
If you go on and try something like this:
POST /users/john HTTP/1.1
it will work, but semantically you are saying that you want to add a resource to the john collection under the users collection.
Once you are using PUT you are refering to a resource or single item, possibly inside a collection. So when you say:
PUT /users/john HTTP/1.1
you are telling to the server update, or create if it doesn't exist, the john resource under the users collection.
Let me highlight some important parts of the spec:
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
Hence, creates a new resource on a collection.
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."
Hence, create or update based on existence of the resource.
POST means "create new" as in "Here is the input for creating a user, create it for me".
PUT means "insert, replace if already exists" as in "Here is the data for user 5".
POST to example.com/users since you don't know the
URL of the user yet, you want the server to create it.
PUT to example.com/users/id since you want to replace/create a specific user.
POSTing twice with the same data means create two identical users with different ids. PUTing twice with the same data creates the user the first and updates him to the same state the second time (no changes). Since you end up with the same state after a
PUT no matter how many times you perform it, it is said to be "equally potent" every time - idempotent. This is useful for automatically retrying requests. No more 'are you sure you want to resend' when you push the back button on the browser.
A general advice is to use
POST when you need the server to be in control of
URL generation of your resources. Use
PUT otherwise. Prefer
I'd like to add my "pragmatic" advice. Use PUT when you know the "id" by which the object you are saving can be retrieved. Using PUT won't work too well if you need, say, a database generated id to be returned for you to do future lookups or updates.
So: To save an existing user, or one where the client generates the id and it's been verified that the id is unique:
PUT /user/12345 HTTP/1.1 <-- create the user providing the id 12345 Host: mydomain.com GET /user/12345 HTTP/1.1 <-- return that user Host: mydomain.com
Otherwise, use POST to initially create the object, and PUT to update the object:
POST /user HTTP/1.1 <--- create the user, server returns 12345 Host: mydomain.com PUT /user/12345 HTTP/1.1 <--- update the user Host: mydomain.com