Fri 20 Mar 2009
It is okay to use POST
Posted by Roy T. Fielding under software architecture, web architecture
[12] Comments
Tim Bray’s article on RESTful Casuistry revisits an odd meme in the REST debates that I’ve been meaning to discredit for a while.
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.
For example, it isn’t RESTful to use GET to perform unsafe operations because that would violate the definition of the GET method in HTTP, which would in turn mislead intermediaries and spiders. It isn’t RESTful to use POST for information retrieval when that information corresponds to a potential resource, because that usage prevents safe reusability and the network-effect of having a URI. But why shouldn’t you use POST to perform an update? Hypertext can tell the client which method to use when the action being taken is unsafe. PUT is necessary when there is no hypertext telling the client what to do, but lacking hypertext isn’t particularly RESTful.
POST only becomes an issue when it is used in a situation for which some other method is ideally suited: e.g., retrieval of information that should be a representation of some resource (GET), complete replacement of a representation (PUT), or any of the other standardized methods that tell intermediaries something more valuable than “this may change something.” The other methods are more valuable to intermediaries because they say something about how failures can be automatically handled and how intermediate caches can optimize their behavior. POST does not have those characteristics, but that doesn’t mean we can live without it. POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.”
I think the anti-POST meme got started because of all the arguments against tunneling other protocols via HTTP’s POST (e.g., SOAP, RSS, IPP, etc.). Somewhere along the line people started equating the REST arguments of “don’t violate HTTP’s method definitions” and “always use GET for retrieval because that forces the resource to have a URI” with the paper tiger of “POST is bad.”
Please, let’s move on. We don’t need to use PUT for every state change in HTTP. REST has never said that we should.
What matters is that every important resource have a URI, therein allowing representations of that resource to be obtained using GET. If the deployment state is an important resource, then I would expect it to have states for undeployed, deployment requested, deployed, and undeployment requested. The advantage of those states is that other clients looking at the resource at the same time would be properly informed, which is just good design for UI feedback. However, I doubt that Tim’s application would consider that an important resource on its own, since the deployment state in isolation (separate from the thing being deployed) is not a very interesting or reusable resource.
Personally, I would just use POST for that button. The API can compensate for the use of POST by responding with the statement that the client should refresh its representation of the larger resource state. In other words, I would return a 303 response that redirected back to the VM status, so that the client would know that the state has changed.
I often find that I chose PUT instead of POST (and end up creating an additional resource in the process) because the behavior requires idempotence. That seems preferable IMO to making POST idempotent. Would you agree?
Stefan, I think it is better to say that we only use PUT when the update action is idempotent and the representation is complete. I think we should define an additional resource whenever we think that resource might be useful to others in isolation, and make use of the GET/PUT methods for that resource, but I don’t think we should define new resources just for the sake of avoiding POST.
PATCH is another option that, once it is sufficiently deployed, might be preferred over POST for sub-resource updates. However, we make these choices for a principled reason, not just because it seems RESTful. Ultimately, the methods should be chosen by the origin server and communicated somehow to the client via the media type or relationship processing rules. If the choice of method doesn’t make any difference to the other components (i.e., neither client nor intermediaries gain any value by using PUT or PATCH over POST), then we should admit that it just doesn’t matter to the architectural style.
The problem I see here is that ‘switching’ to reboot does, infact, seem like an idempotent action – the idea being that a ‘rebooting’ state would actually be a graceful shutdown, to an off state, and back to an on state immediately. Once this rebooting state was initiated any further updates to the rebooting state would be idempotent:
PUT /vm/test-machine/power
{ ‘state’: ‘rebooting’ }
Maybe the kind of reboot Tim is talking about is in fact a quick switching of states to off and then on again (i.e. non-graceful rebooting).
That still doesn’t need a POST – it needs 2 PUT’s on the power state; from on to off, and from off to on again.
GET /vm/test-machine/power
{ ‘state’: ‘on’ }
PUT /vm/test-machine/power
{ ‘state’: ‘off’ }
PUT /vm/test-machine/power
{ ‘state’: ‘on’ }
* once again both of those PUT actions are idempotent, and seem to be more consistent with the nature of the HTTP verbs available for this
Mike, I personally prefer systems that treat monitored state (like power status) as non-editable. I prefer there to be a nice functional relation between the state of the system being monitored and the representations of its state. If we use HTTP methods to edit that state, then I would need a separate resource to monitor the system and tell me the real state. That’s why I would model the machine as having a current power state and a multi-state button for requesting changes to the machine. We could implement that button with PUT instead of POST, but I don’t think we would gain anything by doing so, and I am quite certain that REST does not require one or the other.
Roy,
Thank you, I couldn’t agree more with you. I appreciate all your posts on the REST architectural style and feel exact the same way with regards to its relationship to the Web architecture. I mostly parrot what I believe is your sentiment in the following blog entry I wrote August 2008, in response to a few of your blog posts from the last half of 2008:
http://peskeflog.blogspot.com/2008/08/no-rest-for-wicked.html
Cheers,
Philip Eskelin
Roy,
I agree that support for a PATCH method would be great (but first we’ve got to get people and browsers to even acknowledge that PUT and DELETE exist!). Until then, I think that giving POST this type of functionality makes things more complicated than need be.
POST’s function of treating request entities as “a new subordinate of the resource identified” has been most useful as a sort of factory for creating subordinate resources (e.g. POSTing to /article_id/comment to create a subordinate comment). If we also use POST for updates or a way of achieving partial updates, I think we loose the simplistic nature of our uniform operation set. There is now a bit of additional logic attached to the POST method – treat POST differently according to the context used.
I would agree with Stefan that PUT is still a better choice (in nearly all cases) by it’s definition and due to its idempotent nature.
If partial updates are desired, just provide URIs that have finer granularity (e.g. in our example, PUT /article_id/comment/123/name to edit just the writer’s name) and work with these as atomic units for PUTting. In many cases it can come pretty naturally and doesn’t require anything additional at the persistence layer.
I agree that there are REST zealots out there that get a bit carried away with dos and don’ts, especially since REST is a style and not a set in stone implementation, however, if you do choose HTTP as your uniform interface, I believe that until other methods become adopted, PUT is most appropriate for updates.
Hi Roy,
Thanks for the response – I’m still struggling to understand why ‘monitored’ state should be preferred as non-editable. Probably because I don’t see the power state as a monitored state, but simply as a state that is negotiated via the uniform interface (i.e. monitoring would be mapped to the GET method of the power resource).
Is a button a useful resource to identify? I’m not sure – In real world terms a button/switch seems more like a uniform interface than a resource in and of itself.
I don’t understand why a separate resource for monitoring is necessitated here – could this monitoring not be incorporated into the logic/state behind the power interface? Could that monitoring logic not ‘loop back’ on itself by addressing itself via its HTTP interface; thus keeping relevant intermediaries (and hence clients) ‘in the loop’, so to speak?
That’s probably enough points for now!
Thanks,
Mike
Roy,
I think folks have trouble with using POST to implement a “button” because on the surface it looks a bit like RPC which they have been told is “bad”. Each button has a URI and each button can be thought of as a method that can be invoked. Therefore, the method is represented in the URI and now the sky is falling.
Of course the difference with the RESTful approach is that the URI and instructions for constructing the request body for the POST are represented in hypermedia and not baked into the client as with RPC. As you pointed out in your “REST APIs must by hypertext-driven” posting, most people don’t get this distinction (for reasons touched on in your follow up to that post). I’m not sure how this situation gets “fixed” but I don’t see it changing any time soon.
“Common REST” is all about using PUT and DELETE and organizing your data into CRUD-based interfaces. Hypermedia doesn’t really come into play beyond the recommendation to “put links to other resources in your representations”. This is of course lacking any sort of mechanism (e.g. a form) for constructing the request body of a POST. And so POST just isn’t used in any way other than asking a parent resource to create a child resource and assign a URI to it. e.g. it’s just a PUT where you are asking the server to assign a URI instead of supplying your own.
Common REST is winning mindshare over REST as you defined it. In an environment where the number of links defines authority that means Common REST IS REST.
Google “REST” and you will see that the wikipedia entry has the top position — that entry defines Common REST.
Andrew Wahbe
Andrew, there is no such thing as “Common REST” (nor, for that matter, the alternative declarations of “Low REST” and “High REST”). There is just REST. The problem is that various people have described “I am using HTTP” as some sort of style in itself and then used the REST moniker for branding (or excuses) even when they haven’t the slightest idea what it means. The only way to stop people from misusing the term is to make a negative example of them when they do.
The Wikipedia article suffers from that and also because the folks writing it did not feel a need to constrain themselves to authoritative sources. There is not much I can do about the poor quality of the description aside from editing the article myself, which I’ve avoided doing because it would be too self-referential. Please feel free to fix it.
[…] Roy Okays POST. There’s just too much HTTP method fetishism going around. I understand the appeal, I don’t mind what other people do in the privacy of their own service invocation, and I can see how it acts as counter balance to the SOAP fetish of yore. But it confuses people who should know better, leading them down the path of really creative (read: tightly coupled, unnecessarily complex) verb-based protocols. Hopefully, not for long. […]
Hello Roy.
I just submitted this comment at the InfoQ forum.
http://www.infoq.com/news/2009/04/post-state-appropriate#view_40928
My main concern is not actually the POST, but the way the REST is being forced into applications just by the sake of having it in its name!
Reading the HTTP spec, we can find what Post is supposed to do. And I think we can find a couple of ways for applying these semantics into the problem. But the issue is not the POST at the HTTP Spec, but the POST as REST is supposed to see it.
So, I feel we are trying to make the application fit into REST, instead of analyzing if REST is the suitable option for that application. Since REST is a style, and it is not the only one to work with web or networked applications, I guess the first question would be if my app solution requirements match those of REST and so it is good to follow that style, or we better go with any other that better matches my needs.
In Tim’s problem app, I can just guess that if he is struggling to map the elements and operations into resources and states, in a very artificial way (no natural to the app), we may be tweaking the app to fit the architecture. That is, wagging the dog.
What do you think?
William Martinez Pomares.
William, I talked about the phenomenon of design-by-buzzword in the introduction to my dissertation. It doesn’t surprise me that software companies and consultants continue to use the same marketing and design tactics, even after they’ve updated their buzzword vocabulary to include REST.
Nevertheless, there are plenty of information systems that can be designed using the REST architectural style and gain the associated benefits. Managing cloud instances is certainly one of those applications for which REST is a good fit, as Stu Charlton has described several times. I am glad that Tim and others in the Kenai project are making the attempt, even if the first few iterations have some warts, and I approve of his stance that the design constraints of REST should be used when they are useful, not just because they are RESTful.