POST vs. PUT
This morning, Matthew writes about building RESTful services with the Zend Framework. I have a lot of thoughts on his post, and I might blog more about it later, but right now, I want to focus on David’s comment:
I think the next thing you should cover is how to retrieve put parameters and maybe even attempt to start a discussion on the different school of thoughts about POST vs PUT (Especially in the PHP world).
I know I’m even guilty of mentioning different schools of thought on POST vs. PUT in my talks, but the truth is that REST doesn’t specify what to use for what actions. These are defined by HTTP and not by REST.
Roy Fielding has this to say about the use of HTTP verbs in RESTful applications:
Some people think that REST suggests not to use POST for updates. Search my dissertation and you won’t find any mention of CRUD or POST. The only mention of PUT is in regard to HTTP’s lack of write-back caching. The main reason for my lack of specificity is because the methods defined by HTTP are part of the Web’s architecture definition, not the REST architectural style. Specific method definitions (aside from the retrieval:resource duality of GET) simply don’t matter to the REST architectural style, so it is difficult to have a style discussion about them. The only thing REST requires of methods is that they be uniformly defined for all resources (i.e., so that intermediaries don’t have to know the resource type in order to understand the meaning of the request). As long as the method is being used according to its own definition, REST doesn’t have much to say about it.
The POST vs. PUT debate, however, does rage on in different communities, and some protocols have defined their usage. For example, the Atom Publishing Protocol (RFC 5023) explicitly states in section 4.3 that “POST is used to create” and “PUT is used to edit.”
The important thing to note is that REST doesn’t care how the HTTP verbs are used, as long as they are used properly according to how they are defined in the protocol you are using.
For those interested, HTTP (RFC 2616) defines POST by saying:
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. […] 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.
PUT is defined as:
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.
With this line of thinking, you might come to the conclusion that POST is used for creation of a subordinate resource, while PUT could be used for both creation or modification of a resource. The important distinction is that POST identifies the resource for which the entity should be considered a subordinate; PUT does not.
10 Comments
Perfect. I don't see why people confuse PUT and POST. The HTTP specification, you quote in the blog post, is so clear about it.
It's a blog post, not a blog put, isn't it? :)
I'm not sure I understand your "blog post" vs. "blog put" rationale since, according to the spec, a blog post could be created with either a POST or a PUT request. :-D
Can we tell for simplicity that PUT just takes the Request-Uri and creates it as-is on the server, while POST is more prone to use a CGI script that could eventually do the same as PUT ?
I think a good rule of thumb is the following: you should use POST if you append to a resource and you don't know in advance the URL of the created entity, and you use PUT if you know in advance the URL of the created entity or if you edit something.
And don't forget that PUT should be idempotent!
In a sense it's a bit like INSERT vs REPLACE
PUT is similar to REPLACE
POST is similar to INSERT
@Ben Ramsey
From what I understand, you'd request the server to create a blog pots by making HTTP POST request to the URI, say for example, http://example.com/article. Or http://example.com/myname/a.... In the latter example, the article would be subordinate to the resource 'myname'.
"according to the spec, a blog post could be created with either a POST or a PUT request"
I agree that both POST and PUT can be used to create the resource. It is more likely, we create resources without specifying the URI at which the resource has to be created. Isn't this an uncommon request to create a resource - PUT, http://example.com/article/4?
"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.[...] In contrast, the URI in a PUT request identifies the entity enclosed with the request"
A cool thing about POST: "If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity which describes the status of the request and refers to the new resource, and a Location header. "
So apparently you can use both for updates and creates, its all about the URL. You just have to check the RFCs...
Maybe the problem with PUT and PHP is: PHP usually gets its input through HTML-forms that don't support PUT. And most webbroswers only support POST/GET :(
I'm really curious why many people ignored most HTTP verbs and stuck to only two - GET and POST, from the early days of HTTP?
@Sudheer: That's actually a really good question. I'll do some digging around and see if I can come up with a little history lesson on that. :-)