PUT versus POST

2 views
Skip to first unread message

Dan Yoder

unread,
Apr 30, 2009, 2:12:50 AM4/30/09
to ruby...@googlegroups.com
There has been some recent discussion on #waves about PUT versus POST. Since it's an important topic, rather than post (heh) there and risk having only a few of us catch the conversation, I figured I'd move it over here. What follows is my current understanding of how to use these methods effectively.

As always, I start with the HTTP specification, which clearly states that you use PUT to store / associate a value using / with a specific URI. This whole business of using PUT to create and POST to update is I think one of those things that came about because of the browsers use POST (more on this below). According to the specification, the distinction is not about create versus update, but rather whether the body of the request is directly (PUT) or indirectly (POST) associated with a given URI.

Put another way, PUT is very specific. It says "this data is to be associated with this URI." This can be a create or an update, it doesn't matter. It is the counterpart to GET. I can GET a resource or PUT a resource. It makes no difference if the resource existed before or not. All that matters is that the URI thereafter refers to the thing that was PUT.

Meanwhile, POST is for when you don't really want to update the entire resource, but you want the resource to do something for you, on your behalf. Typically this is because there is no resource (or, more specifically, no URI) associated specifically with the update, and thus you cannot use PUT. There are a lot of contexts where this might make sense. The specification alludes to several:
      - Annotation of existing resources;
      - Posting a message to a bulletin board, newsgroup, mailing list,
or similar group of articles;
      - Providing a block of data, such as the result of submitting a
form, to a data-handling process;
      - Extending a database through an append operation.
 It is clearly the third one that caused most of the confusion. However, it shouldn't have, if you read it closely. It says nothing of creating or updating a resource, but rather submitting data to a process. Which is exactly the sort of vague in-between-the-cracks sort of thing POST is meant for. Fielding elaborates in his most recent blog post: POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing." This can include updates to a resource when it applies to a "subordinate" part of it.

There are many things that don't make sense outside of a larger context of some kind, but are complex enough that they require their own data structures. Street addresses are like this, as one example. The street address is subordinate to, say, a person. Now that person can be included in other contexts (such as your address book) but it also makes sense independent of them. Thus, a person warrants its own dedicated URI, which allows other resources to link to it. However, an address might not not have its own URI because it never makes sense outside of the context of a given person. Since it does not have its own URI, you can only update it via the person resource. In that case, when you update the address, you might choose to POST ("I'm updating the address, not the entire resource").

Now ... lest this seem like meaningless drivel (i.e., why not always use POST), let's consider the Twitter API. For performance reasons, Twitter does not return a list of followers when you ask for a user profile resource. Some people have tens-of-thousands of followers ... but, at the same time, a user's followers by themselves don't really make sense outside of the user's context. The first mistake that Twitter makes is not linking to a resource so I can GET the followers without having to know the URL structure in advance. But let's put that aside for a moment.

In any case, I have a resource describing the followers for this user. Let's say I want to add a follower to that resource. I don't want to PUT that, because I'd have to include the entire list of followers. So I can POST the one additional follower to that URL. Since I don't want to send back the entire list of followers, I can reply with a 204 (No Content) to indicate that the update was a success. The same logic applies to removing a follower as well. There is no resource to DELETE, so I POST ... I am not deleting the follower (a user) but updating the state of the followers reource.

In other words, all your basics are covered by GET, PUT, and DELETE. They have highly standardized semantics that can be understood by intermediaries (firewalls, routers, proxies, etc.). POST is the "catch-all" for everything else, since, as it happens, the world doesn't always fall into nice neat GET, PUT, DELETE semantics. The browsers use POST because they don't know what the form is doing - as it says in the spec, they only know they are requesting data processing by a given resource. Which is not to say they might not have allowed PUT, but that's another story.

Dan

Jerry

unread,
Apr 30, 2009, 7:33:34 AM4/30/09
to rubywaves
Dan,

very lucid, thank you.

> In any case, I have a resource describing the followers for this user.
> Let's say I want to add a follower to that resource. I don't want to PUT that,...

A query from a REST-newbie. From a RESTful design perspective, why
isn't a follower a sub-resource you would PUT (I'm thinking of the
Rails-style URL /user/66/follower/34)? Why have all-my-followers as
the resource? Is it just an example and essentially irrelevant or a
fundamental choice arising from REST and the fact that 'followers make
no sense alone'? If the latter, any hints as to where can I read more
about these sort of design decisions?

Many thanks,
Jerry

Eero Saynatkari

unread,
Apr 30, 2009, 11:23:30 AM4/30/09
to rubywaves
Excerpts from Daniel Yoder's message of Thu Apr 30 09:12:50 +0300 2009:

> In other words, all your basics are covered by GET, PUT, and DELETE. They
> have highly standardized semantics that can be understood by intermediaries
> (firewalls, routers, proxies, etc.). POST is the "catch-all" for everything
> else, since, as it happens, the world doesn't always fall into nice neat
> GET, PUT, DELETE semantics. The browsers use POST because *they don't know
> what the form is doing* - as it says in the spec, they only know they are

> requesting data processing by a given resource. Which is not to say they
> might not have *allowed* PUT, but that's another story.

There is one circumstance that is slightly more complex
than the Twitter followers scenario -- which is certainly
a useful problem space to consider: even though Followers
are Users in their own right, just being a User does not
necessitate also being a Follower; ergo, the two can be
separated.

How about, though, something like a blog Article in some
article Index? We do in fact have (possibly) two separate
resources, and both of them are identifiable directly. In
such a case, it would be semantically correct to either PUT
Articles directly (creation/update does not matter), or to
POST through the Index. It could be argued that using PUT
would mean that Index does not "learn" about the Article,
but that implies a, well, implied relationship between the
two (which we want to usually avoid even if it actually
does exist.)

If both methods are valid, how to structure it so that it
does not allow (or discourages) duplication of logic? (E.g.
maybe a POST would do an internal PUT?)

And, if we should determine that only one of these methods
should be used in this situation, how would that be easily
communicable in constructing the resources?

And finally, how to best represent these in terms of links
and transitions?

It is (I guess) fine to say that the system is so flexible
that it allows both, but I have a hard time seeing value in
that -- there seems to be nothing *gained* by the option of
using either, except not having to agree on a convention. It
bothers me that REST is so very ill-defined in some respects
and often some of the explanations sound like so much hand-
wavy BS; sometimes HTTP matters, but hey, sometimes it does
not. It is quite possible that I am just not smart enough
to get these radical ideas, but it seems to me that if one
cannot define REST in some manner, then it is impossible to
structure a framework around encouraging it. REST happens.

I have my ideas on how to try to solve this and steer the
users toward a convention, but I would be interested in
hearing some more thoughts on the matter, and in particular
the PUT/POST dilemma.


Eero (rue)

--
Magic is insufficiently advanced technology.

Dan Yoder

unread,
Apr 30, 2009, 10:17:15 PM4/30/09
to ruby...@googlegroups.com

very lucid, thank you.

thank goodness. you're welcome.
 

As far as reading about this, I haven't found a whole lot out there, which is why I'm beginning to blog about it (REST articles are cross-posted to the Waves blog thought). A lot of it is in the HTTP spec and you can get hints from Fielding's blog. But there is a surprising amount of confusion around the whole topic.

One hint: when Fielding says "hypertext" I think you can safely read it as "linked data" (Tim Berners-Lee's term).

As to the Rails conventions, there are two major problems with it. The first is that it introduces unnecessary coupling. From that standpoint, it isn't REST and it is arguably a poor interface. The second problem is that it is goofy semantically.

Let's start with the semantics. In Ruby, I might have a class representing a User with an attribute called followers. You would expect that attribute to be an array of Users, right? The convention above is the equivalent of introducing Follower objects instead so that you can add and delete them instead of simply adding and deleting from the array directly. It isn't wrong, per se, just unnecessary. You can kind of see this by asking yourself what exactly is the value being PUT at that URL? Is it the same value being returned when I do a GET? No, because there isn't really a value there.

You can reduce the coupling by having a URI for the user (say, http://blather.com/users/66) and then access the followers resource using a link included in the response. Now I have one less thing about the interface I need to know in advance (and, which, if it changes, will break my client).

Hope that helps.

Dan



Many thanks,
 Jerry


ab5tract

unread,
May 1, 2009, 1:28:24 AM5/1/09
to rubywaves

> You can reduce the coupling by having a URI for the user (say,http://blather.com/users/66) and then access the followers resource using a
> link included in the response. Now I have one less thing about the interface
> I need to know in advance (and, which, if it changes, will break my client).

Do you mean "will _not_ break my client" ?

Awesome stuff btw, I'm interested in seeing this expressed in the new
DSL. Juxtaposing both approaches both in Waves might help to clear
things up a bit, me thinks.

Lawrence Pit

unread,
May 1, 2009, 1:41:10 AM5/1/09
to ruby...@googlegroups.com

> As to the Rails conventions, there are two major problems with it. The
> first is that it introduces unnecessary coupling. From that
> standpoint, it isn't REST and it is arguably a poor interface.

Not quite. The example given is not rails convention. If you have say this:

/spaces/123/topics/456

then this doesn't make sense, and indeed you have unnecessary coupling.
That's why the suggestion is to have this instead:

/topics/456

However, suppose IDs aren't used, but permalinks instead. Now it is
necessary to specify the spaces namespace in the URI like:

/spaces/123/topics/my-first-topic

This is because it is possible to have a topic named "My First Topic" in
two different spaces. I.e., the uniqueness of the topic permalink is
scoped by space. Rails happens to support these kind of URIs. And I'd
say this fits the REST style.


> The second problem is that it is goofy semantically.

That's because the original example was goofy. Has nothing to do with rails.

> Let's start with the semantics. In Ruby, I might have a class
> representing a User with an attribute called followers. You would
> expect that attribute to be an array of Users, right? The convention
> above is the equivalent of introducing Follower objects instead so
> that you can add and delete them instead of simply adding and deleting
> from the array directly. It isn't wrong, per se, just unnecessary.

In rails you can't actually do this. (well, you can if you try really
hard I suppose, but it's certainly not convention)

> You can kind of see this by asking yourself what exactly is the value
> being PUT at that URL? Is it the same value being returned when I do a
> GET? No, because there isn't really a value there.
>
> You can reduce the coupling by having a URI for the user (say,
> http://blather.com/users/66) and then access the followers resource
> using a link included in the response. Now I have one less thing about
> the interface I need to know in advance (and, which, if it changes,
> will break my client).

That's how rails actually does it. To add/delete followers one PUTs
updates to the /users/66 resource, or alternatively POSTs to
/users/66/followers.


Cheers,
Lawrence

Dan Yoder

unread,
May 1, 2009, 2:43:15 AM5/1/09
to ruby...@googlegroups.com
Thanks, Lawrence. I should not have said "Rails conventions," since I am not actually all that familiar with them. My comment apply only to the example given and only to Rails (or any other framework or conventions) to the extent that it reflects best practice.



On Thu, Apr 30, 2009 at 10:41 PM, Lawrence Pit <lawren...@gmail.com> wrote:

/spaces/123/topics/my-first-topic

This is because it is possible to have a topic named "My First Topic" in
two different spaces. I.e., the uniqueness of the topic permalink is
scoped by space. Rails happens to support these kind of URIs. And I'd
say this fits the REST style.

Yes. I think the only REST has to say about it is that there should be no semantic meaning to a URI. It's just an identifier. If it happens to be constructed to be human friendly, great, but REST doesn't care.

 
That's how rails actually does it. To add/delete followers one PUTs
updates to the /users/66 resource, or alternatively POSTs to
/users/66/followers.

The PUT version would have to include all the followers, not just the new one.

Cheers,
Lawrence

Nice to see you again ... =o)

Dan

Dan Yoder

unread,
May 1, 2009, 3:02:52 AM5/1/09
to ruby...@googlegroups.com
The Article / Blog dilemma instructive, but I don't think it is as tricky as it might seem.

Basically, HTTP defines a giant distributed hash, right? The first class operators are GET, PUT, and DELETE, the interface to this hash. These have the most well-defined semantics, which allows intermediaries to deal with more intelligently. Whenever it is natural, you should use them.

POST is there for the cases where it becomes awkward to model the interface as a distributed hash. It is a classic 80/20 thing. Most of the time, a distributed hash is a decent abstraction. The 20% of the time the real world refuses to line up nicely as key-value pairs, you have POST.

In this case, you would simply PUT the article with a link to the blog, since there is nothing awkward about doing that. You would not use POST. Now, this is assuming that we consider the article to be resource in its own right, which was the scenario as I understood it.

I don't think there is anything all that radical about REST or HTTP. It just seems that way because there was this ill-advised attempt to map CRUD to HTTP, compounded by the fact that REST is defined by a dissertation by a guy who clearly isn't thrilled with explaining himself to Web developers.

Regards,
Dan

Eero Saynatkari

unread,
May 1, 2009, 5:57:15 AM5/1/09
to rubywaves
Excerpts from Daniel Yoder's message of Fri May 01 10:02:52 +0300 2009:

> The Article / Blog dilemma instructive, but I don't think it is as tricky as
> it might seem.
>
> Basically, HTTP defines a giant distributed hash, right? The first class
> operators are GET, PUT, and DELETE, the interface to this hash. These have
> the most well-defined semantics, which allows intermediaries to deal with
> more intelligently. Whenever it is natural, you should use them.
>
> POST is there for the cases where it becomes awkward to model the interface
> as a distributed hash. It is a classic 80/20 thing. Most of the time, a
> distributed hash is a decent abstraction. The 20% of the time the real world
> refuses to line up nicely as key-value pairs, you have POST.
>
> In this case, you would simply PUT the article with a link to the blog,
> since there is nothing awkward about doing that. You would not use POST.
> Now, this is assuming that we consider the article to be resource in its own
> right, which was the scenario as I understood it.

Here is what HTTP 1.1 has to say:

> The POST method is used to request that the origin server
> accept the entity enclosed in the request as a new sub-
> ordinate of the resource identified by the Request-URI in
> the Request-Line. POST is designed to allow a uniform
> method to cover the following functions:


>
> - Annotation of existing resources;
>
> - Posting a message to a bulletin board, newsgroup,
> mailing list, or similar group of articles;
>
> - Providing a block of data, such as the result of
> submitting a form, to a data-handling process;
>
> - Extending a database through an append operation.
>

> 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.
>
> <snip />

The second use-case is exactly the scenario with the Index
and some Article. We may absolutely decree that it applies
only when the subordinate is not (possibly) a resource in
its own right, and PUT should be used instead, but /the spec
does not say that/.

> I don't think there is anything all that radical about REST or HTTP. It just
> seems that way because there was this ill-advised attempt to map CRUD to
> HTTP, compounded by the fact that REST is defined by a dissertation by a guy
> who clearly isn't thrilled with explaining himself to Web developers.

Thing is, if it seems that no-one understands the argument,
the problem might be in the argument, not the audience.

That may apply inversely, too: maybe my argument does not
make any sense, but it seems to me that Roy and the Powers
that Be (awesome band name, by the by) are not adequately
addressing the few relatively minor inconsistencies that are
actively harming the adoption and effective use of a model
that is otherwise very solid.

Dan Yoder

unread,
May 1, 2009, 10:54:21 AM5/1/09
to ruby...@googlegroups.com
On Fri, May 1, 2009 at 2:57 AM, Eero Saynatkari <regist...@kittensoft.org> wrote:
Here is what HTTP 1.1 has to say [...]


The second use-case is exactly the scenario with the Index
and some Article. We may absolutely decree that it applies
only when the subordinate is not (possibly) a resource in
its own right, and PUT should be used instead, but /the spec
does not say that/.

Correct. But Fielding does say that on his blog:

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.”
 
And the spec isn't entirely silent, since it does talk about the data being POSTed as being subordinate to an existing resource and never refers to it in terms of itself being a resource. But I only got clarity on that from the blog, not the spec.

Thing is, if it seems that no-one understands the argument,
the problem might be in the argument, not the audience.

Yes and no. There's no question REST became a buzzword and a lot of things were labeled "RESTful" that were not. Couple that with a lack of developer-friendly exposition by Fielding (and others, many of whom seem to want to be obscure in order to be part of the clique), and it is easy to see the confusion. I don't blame the spec, per se, since most specs are written by committee and poor on addressing the "big picture."

So I'm not blaming the audience, here. Not at all. I'm just saying there is a lot of misinformation out there and that the folks who know what the intent of all this was - and you can't deny that it has been mind-bogglingly succesful as a distributed computing architecture - haven't been terribly helpful.

What I don't believe is that there is any intrinsic problem with the premise. I'm not going to blame HTTP or the constraints of REST or the Web or whatever for the fact that REST became a buzzword and that led to a lot of confusion.
 
That may apply inversely, too: maybe my argument does not
make any sense, but it seems to me that Roy and the Powers
that Be (awesome band name, by the by) are not adequately
addressing the few relatively minor inconsistencies that are
actively harming the adoption and effective use of a model
that is otherwise very solid.

I agree. It is very frustrating. I don't think Roy & Co. are doing Web architecture any favors by being so curmudgeonly about helping us understand the intent. I will say that I am glad Roy is blogging ... that has helped me tremendously, even if it is, at times, like translating Sanskrit. That said, he is a researcher and we are engineers; and his dissertation was, in fact, hijacked by a bunch of buzz-addicted opportunists, which might have irritated me, too. =)

Dan


Eero Saynatkari

unread,
May 4, 2009, 1:34:06 PM5/4/09
to rubywaves
Excerpts from Daniel Yoder's message of Fri May 01 17:54:21 +0300 2009:

> On Fri, May 1, 2009 at 2:57 AM, Eero Saynatkari <
> regist...@kittensoft.org> wrote:
>
> > Here is what HTTP 1.1 has to say [...]
> >
> > The second use-case is exactly the scenario with the Index
> > and some Article. We may absolutely decree that it applies
> > only when the subordinate is not (possibly) a resource in
> > its own right, and PUT should be used instead, but /the spec
> > does not say that/.
>
>
> Correct. But Fielding does say that on his blog:

(Only, what, a decade later? :)

> And the spec isn't entirely silent, since it does talk about the data being
> POSTed as being subordinate to an existing resource and never refers to it
> in terms of itself being a resource. But I only got clarity on that from the
> blog, not the spec.

Sure, but the examples given in the definition confue the
issue by not distinguishing as "newsgroup articles without
separate representation." Furthermore, it can certainly be
argued that a not-yet-existing blogpost, for example, does
not have a resource identifier yet -- this would be the one
referred to in the response to a POST.

> Thing is, if it seems that no-one understands the argument,
> > the problem might be in the argument, not the audience.
>
>
> Yes and no. There's no question REST became a buzzword and a lot of things
> were labeled "RESTful" that were not. Couple that with a lack of
> developer-friendly exposition by Fielding (and others, many of whom seem to
> want to be obscure in order to be part of the clique), and it is easy to see
> the confusion. I don't blame the spec, per se, since most specs are written
> by committee and poor on addressing the "big picture."
>
> So I'm not blaming the audience, here. Not at all. I'm just saying there is
> a lot of misinformation out there and that the folks who know what the
> intent of all this was - and you can't deny that it has been mind-bogglingly
> succesful as a distributed computing architecture - haven't been terribly
> helpful.

I blame the spec a bit myself -- and to be clear, by "the
argument" above, I was referring to the "REST architecture"
argument and not e.g. your argumentation.

Dan Yoder

unread,
May 4, 2009, 2:31:27 PM5/4/09
to ruby...@googlegroups.com
On Mon, May 4, 2009 at 10:34 AM, Eero Saynatkari <regist...@kittensoft.org> wrote:
> Correct. But Fielding does say that on his blog:

(Only, what, a decade later? :)

Right. As I said, not terribly eager to help ...
 
Sure, but the examples given in the definition confue the
issue by not distinguishing as "newsgroup articles without
separate representation." Furthermore, it can certainly be
argued that a not-yet-existing blogpost, for example, does
not have a resource identifier yet -- this would be the one
referred to in the response to a POST.

If the resource doesn't exist, I don't think a POST semantically makes much sense.
 
I blame the spec a bit myself -- and to be clear, by "the
argument" above, I was referring to the "REST architecture"
argument and not e.g. your argumentation.

Thanks. =) Except that my argument is that REST-based architecture is a good thing ... so I'm not sure where that leaves us. ;)

I will say that I agree that the whole thing could be much clearer and that Fielding, et al, could probably have avoided a lot of confusion just by speaking up a little earlier. At one point, I contacted Mark Baker (who also writes a REST blog) and told him about Waves and asked him for any insights and he said something along the lines of "You mean like Rails?" and so I left it alone.

(Again, not to bash Rails .. the point being that there seems to be little interest in encouraging frameworks to better support REST ...)

But ... that doesn't mean it isn't a very solid archiectural approach. The question of course becomes whether or not we have really just defined something new, perhaps closely related to REST, but not entirely the same, since we can't read Fielding's mind.

And I get the feeling, Eero, that is part of the appeal for you, is that we can actually just do something related but also more practical. So ... I am not sure. There is no reason to adhere to a given approach if it is demonstrably not the best one for a given problem.

But my reasoning is that inferring design constraints from something that is proven to work on a very large scale and across a diverse array of solutions isn't really all that bad a practice. And I feel confident, perhaps unreasonably so, that my inferences have a sound basis ...

Also, this whole issue is one of the reasons I have been emphasizing ROA more so than REST. ROA should be REST-compliant, ideally, but it does not need to be perfectly rigorous about it since we aren't calling it REST.

And the great thing about the Foundations approach is that we can do both!

Dan

Reply all
Reply to author
Forward
0 new messages