First of all, some definitions:
PUT is defined in Section 9.6 RFC 2616:
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.
PATCH is defined in RFC 5789:
The PATCH method requests that a set of changes described in the request entity be applied to the resource identified by the Request- URI.
Also according to RFC 2616 Section 9.1.2 PUT is Idempotent while PATCH is not.
Now lets take a look at a real example. When I do POST to /users
with the data {username: 'skwee357', email: 'skwee357@domain.com'}
and the server is capable of creating a resource, it will respond with 201 and resource location (lets assume /users/1
) and any next call to GET /users/1
will return {id: 1, username: 'skwee357', email: 'skwee357@domain.com'}
.
Now lets say I want to modify my email. Email modification is considered "a set of changes" and therefor I should PATCH /users/1
with "patch document". In my case it would be a json {email: 'skwee357@newdomain.com'}
. The server then returns 200 (assuming permission are ok). This brings me to first question:
- PATCH is NOT idempotent. It said so in RFC 2616 and RFC 5789. However if I'll issue the same PATCH request (with my new email) Ill get the same resource state (with my email being modified to the requested value). Why isn't PATCH then idempotent?
PATCH is a relatively new verb (RFC introduced in March 2010), and it comes to solve the problem of "patching" or modifying a set of fields. Before PATCH was introduced, everybody used PUT to update resource. But after PATCH was introduced, it leaves me confused what is PUT used for then? And this brings me to second (and the main) question:
- Whats the real difference between PUT and PATCH? I've read somewhere the PUT might be used to replace entire entity under specific resource, so one should send the full entity (instead of set of attributes as with PATCH). What is the real practical usage for such case? When would you like to replace / overwrite an entity under specific resource URI and why such operation is not considered as updating / patching the entity? The only practical use case I see for PUT is issuing a PUT on collection, i.e.
/users
to replace the entire collection. Issuing PUT on a specific entity makes no sense after PATCH was introduced. Am I wrong?
NOTE: When I first spent time reading about REST, idempotence was a confusing concept to try to get right. I still didn't get it quite right in my original answer, as further comments (and Jason Hoetger's answer) have shown. For a while, I have resisted updating this answer extensively, to avoid effectively plagiarizing Jason, but I'm editing it now because, well, I was asked to (in the comments).
After reading my answer, I suggest you also read Jason Hoetger's excellent answer to this question, and I will try to make my answer better without simply stealing from Jason.
Why is PUT idempotent?
As you noted in your RFC 2616 citation, PUT is considered idempotent. When you PUT a resource, these two assumptions are in play:
You are referring to an entity, not to a collection.
The entity you are supplying is complete (the entire entity).
Let's look at one of your examples.
If you POST this document to
/users
, as you suggest, then you might get back an entity such asIf you want to modify this entity later, you choose between PUT and PATCH. A PUT might look like this:
You can accomplish the same using PATCH. That might look like this:
You'll notice a difference right away between these two. The PUT included all of the parameters on this user, but PATCH only included the one that was being modified (
email
).When using PUT, it is assumed that you are sending the complete entity, and that complete entity replaces any existing entity at that URI. In the above example, the PUT and PATCH accomplish the same goal: they both change this user's email address. But PUT handles it by replacing the entire entity, while PATCH only updates the fields that were supplied, leaving the others alone.
Since PUT requests include the entire entity, if you issue the same request repeatedly, it should always have the same outcome (the data you sent is now the entire data of the entity). Therefore PUT is idempotent.
Using PUT wrong
What happens if you use the above PATCH data in a PUT request?
(I'm assuming for the purposes of this question that the server doesn't have any specific required fields, and would allow this to happen... that may not be the case in reality.)
Since we used PUT, but only supplied
email
, now that's the only thing in this entity. This has resulted in data loss.This example is here for illustrative purposes -- don't ever actually do this. This PUT request is technically idempotent, but that doesn't mean it isn't a terrible, broken idea.
How can PATCH be idempotent?
In the above example, PATCH was idempotent. You made a change, but if you made the same change again and again, it would always give back the same result: you changed the email address to the new value.
My original example, fixed for accuracy
I originally had examples that I thought were showing non-idempotency, but they were misleading / incorrect. I am going to keep the examples, but use them to illustrate a different thing: that multiple PATCH documents against the same entity, modifying different attributes, do not make the PATCHes non-idempotent.
Let's say that at some past time, a user was added. This is the state that you are starting from.
After a PATCH, you have a modified entity:
If you then repeatedly apply your PATCH, you will continue to get the same result: the email was changed to the new value. A goes in, A comes out, therefore this is idempotent.
An hour later, after you have gone to make some coffee and take a break, someone else comes along with their own PATCH. It seems the Post Office has been making some changes.
Since this PATCH from the post office doesn't concern itself with email, only zip code, if it is repeatedly applied, it will also get the same result: the zip code is set to the new value. A goes in, A comes out, therefore this is also idempotent.
The next day, you decide to send your PATCH again.
Your patch has the same effect it had yesterday: it set the email address. A went in, A came out, therefore this is idempotent as well.
What I got wrong in my original answer
I want to draw an important distinction (something I got wrong in my original answer). Many servers will respond to your REST requests by sending back the new entity state, with your modifications (if any). So, when you get this response back, it is different from the one you got back yesterday, because the zip code is not the one you received last time. However, your request was not concerned with the zip code, only with the email. So your PATCH document is still idempotent - the email you sent in PATCH is now the email address on the entity.
So when is PATCH not idempotent, then?
For a full treatment of this question, I again refer you to Jason Hoetger's answer. I'm just going to leave it at that, because I honestly don't think I can answer this part better than he already has.
Let me quote and comment more closely the RFC 7231 section 4.2.2, already cited in earlier comments :
So, what should be "the same" after a repeated request of an idempotent method? Not the server state, nor the server response, but the intended effect. In particular, the method should be idempotent "from the point of view of the client". Now, I think that this point of view shows that the last example in Dan Lowe's answer, which I don't want to plagiarize here, indeed shows that a PATCH request can be non-idempotent (in a more natural way than the example in Jason Hoetger's answer).
Indeed, let's make the example slightly more precise by making explicit one possible intend for the first client. Let's say that this client goes through the list of users with the project to check their emails and zip codes. He starts with user 1, notices that the zip is right but the email is wrong. He decides to correct this with a PATCH request, which is fully legitimate, and sends only
since this is the only correction. Now, the request fails because of some network issue and is re-submitted automatically a couple of hours later. In the meanwhile, another client has (erroneously) modified the zip of user 1. Then, sending the same PATCH request a second time does not achieve the intended effect of the client, since we end up with an incorrect zip. Hence the method is not idempotent in the sense of the RFC.
If instead the client uses a PUT request to correct the email, sending to the server all properties of user 1 along with the email, his intended effect will be achieved even if the request has to be re-sent later and user 1 has been modified in the meanwhile --- since the second PUT request will overwrite all changes since the first request.
I was curious about this as well and found a few interesting articles. I may not answer your question to its full extent, but this at least provides some more information.
http://restful-api-design.readthedocs.org/en/latest/methods.html
Given that, then a PUT should send the entire object. For instance,
This would effectively update the email. The reason PUT may not be too effective is that your only really modifying one field and including the username is kind of useless. The next example shows the difference.
Now, if the PUT was designed according the spec, then the PUT would set the username to null and you would get the following back.
When you use a PATCH, you only update the field you specify and leave the rest alone as in your example.
The following take on the PATCH is a little different than I have never seen before.
http://williamdurand.fr/2014/02/14/please-do-not-patch-like-an-idiot/
You are more or less treating the PATCH as a way to update a field. So instead of sending over the partial object, you're sending over the operation. i.e. Replace email with value.
The article ends with this.
Now, I don't know if I particularly agree with the article as many commentators point out. Sending over a partial representation can easily be a description of the changes.
For me, I am mixed on using PATCH. For the most part, I will treat PUT as a PATCH since the only real difference I have noticed so far is that PUT "should" set missing values to null. It may not be the 'most correct' way to do it, but good luck coding perfect.
The difference between PUT and PATCH is that:
PATCH requires some "patch language" to tell the server how to modify the resource. The caller and the server need to define some "operations" such as "add", "replace", "delete". For example:
Instead of using explicit "operation" fields, the patch language can make it implicit by defining conventions like:
in the PATCH request body:
With the above convention, the PATCH in the example can take the following form:
Which looks more concise and user-friendly. But the users need to be aware of the underlying convention.
With the operations I mentioned above, the PATCH is still idempotent. But if you define operations like: "increment" or "append", you can easily see it won't be idempotent anymore.
Though Dan Lowe's excellent answer very thoroughly answered the OP's question about the difference between PUT and PATCH, its answer to the question of why PATCH is not idempotent is not quite correct.
To show why PATCH isn't idempotent, it helps to start with the definition of idempotence (from Wikipedia):
In more accessible language, an idempotent PATCH could be defined as: After PATCHing a resource with a patch document, all subsequent PATCH calls to the same resource with the same patch document will not change the resource.
Conversely, a non-idempotent operation is one where f(f(x)) != f(x), which for PATCH could be stated as: After PATCHing a resource with a patch document, subsequent PATCH calls to the same resource with the same patch document do change the resource.
To illustrate a non-idempotent PATCH, suppose there is a /users resource, and suppose that calling
GET /users
returns a list of users, currently:Rather than PATCHing /users/{id}, as in the OP's example, suppose the server allows PATCHing /users. Let's issue this PATCH request:
Our patch document instructs the server to add a new user called
newuser
to the list of users. After calling this the first time,GET /users
would return:Now, if we issue the exact same PATCH request as above, what happens? (For the sake of this example, let's assume that the /users resource allows duplicate usernames.) The "op" is "add", so a new user is added to the list, and a subsequent
GET /users
returns:The /users resource has changed again, even though we issued the exact same PATCH against the exact same endpoint. If our PATCH is f(x), f(f(x)) is not the same as f(x), and therefore, this particular PATCH is not idempotent.
Although PATCH isn't guaranteed to be idempotent, there's nothing in the PATCH specification to prevent you from making all PATCH operations on your particular server idempotent. RFC 5789 even anticipates advantages from idempotent PATCH requests:
In Dan's example, his PATCH operation is, in fact, idempotent. In that example, the /users/1 entity changed between our PATCH requests, but not because of our PATCH requests; it was actually the Post Office's different patch document that caused the zip code to change. The Post Office's different PATCH is a different operation; if our PATCH is f(x), the Post Office's PATCH is g(x). Idempotence states that
f(f(f(x))) = f(x)
, but makes no guarantes aboutf(g(f(x)))
.