Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

lachoy (1663)

lachoy
  chris.winters@gmail.com
http://www.cwinters.com/

I am actually Chris Winters; I am actually living in Pittsburgh, Pennsylvania, USA; I am actually married and have three cats. (Guess what one of them is named?) I am the "OpenInteract" guy, which could be good or bad.

Journal of lachoy (1663)

Friday June 16, 2006
12:27 PM

PUT vs POST

[ #29930 ]

In reading up on REST principles and arguments over the last couple of weeks, I've run into quite a bit of confusion about what some of the HTTP methods mean. GET and DELETE are straightforward, no confusion. But PUT and POST are another matter.

For instance, in his excellent article How to Create a REST Protocol, Joe Gregorio has the following table:

HTTP Method CRUD Action Description POST CREATE Create a new resource GET RETRIEVE Retrieve a representation of a resource PUT UPDATE Update a resource DELETE DELETE Delete a resource

While it's useful on the surface to think about mapping HTTP verbs to SQL verbs, I think that because there's overlap between PUT and POST we're hiding an important impedance mismatch between data-as-relational-records and data-as-manipulatable-resources. For instance, the table implies that PUT is like the SQL UPDATE, but by common acceptance PUT shouldn't be used to just update 1 field of 20 as commonly done with SQL UPDATEs. So when you PUT an update with just a change of a customer's first name and a number of other fields are modified (because you didn't supply values for them), you might get a little freaked out.

Here's a similar view from Paul Prescod, who says in his Common REST Mistakes:

Do not overuse POST. POST is in some senses the "most flexible" of HTTP's methods. It has a slightly looser definition than the other methods and it supports sending information in and getting information out at the same time. Therefore there is a tendency to want to use POST for everything. In your first REST Web Service, I would say that you should only use POST when you are creating a new URI. Pretend POST means "create new URI as child of the current URI." As you get more sophisticated, you may decide to use POST for other kinds of mutations on a resource. One rule of thumb is to ask yourself whether you are using POST to do something that is really a GET, DELETE or PUT, or could be decomposed into a combination of methods. (emphasis added)

To muddy the waters even more, here's what the HTTP 1.1 RFC says about POST:

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.

...and about PUT:

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.

It's easy to see where the confusion is because according to the spec:

  • POST can be used as an UPDATE (annotating an existing resource) and as an INSERT (posting a message to a bulletin board)
  • PUT can be used as a full UPDATE (replacing entirely an existing resource) and as an INSERT (adding a new resource)

So when you're using HTTP methods as an integral part of your application it's important to clarify how you're interpreting PUT and POST.

Here's my first attempt:

  • PUT is create or replace
  • POST is partial or complete update of an existing resource, or adding metadata to an existing resource

Some examples. Add a new customer:

PUT /customer HTTP/1.1
Content-Type: text/xml
<customer>...</customer>

Update all fields of customer with ID 1234:

PUT /customer/1234 HTTP/1.1
Content-Type: text/xml
<customer>...</customer>

Update the 'firstName' field of customer with ID 1234:

POST /customer/1234 HTTP/1.1
Content-Type: text/xml
<customer>
  <firstName>Napoleon</firstName>
</customer>

That's easy. Now, for something more complicated: what if I want to add a new address to a customer? I could do it with either one depending on how the resources are structured. Is an address a separately addressable resource, or is it completely dependent on a customer? Can there be more than one address of a particular type, or can a customer have as many addresses as necessary?

It's probably a good rule of thumb to make every resource separately addressable. You never know how you might want to use them in the future. So we'll use a PUT and include a link to our related resource:

PUT /address HTTP/1.1
Content-Type: text/xml
<address>
  <street-address>111 Main Street<street-address>
  <city>Pittsburgh</city>
  <state>PA</state>
  <postal>15217</postal>
  <customer href="/customer/1234" />
</address>

That seems to work pretty well. There may be cases I haven't thought of yet, we'll see how they can fit into this scheme.

Posted from cwinters.com; read original

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • I think the most important distinction to remember between PUT vs. POST is that PUT is intended to be idempotent and POST is not.

    You should be able to PUT the same resource with the same data and it have no additional effect, after the first time.

    Remember also that the agent (client) submitting a PUT request should be able to tell if this is a new resource being created through the 201 response, although in practice this is heavily abused and many programs always return 200 responses for all success.
    • Yep, I forgot to mention this. An interesting thing about the idempotence discussion is that people confuse "I submit foo once or twenty times and get the same response" versus "I will have no side effects on the server from submitting foo."
  • I usually end up using POST for all CREATES, since I find no good way to pregenerate the URI to the thing I'm creating. Say you have a resource /videos which is the root to a listing of all the videos in your system. Each individual video might have a URI like /video/100, /video/110, etc. But if I want to create a new video using put I have to PUT the file to something like /video/120 but how do I know it's 120? Usually this ends up being autogenerated by a database anyway. So I find it most easy to PO
    --
    Waiting on the Road to Eventually, I lost my Place On Line
    • From what I've read the common thing to do is PUT to the 'collection' URI -- in your case, you'd do 'PUT /videos'; the server would return a '201 Created' header with the URI of the resource you just uploaded, like: '/video/110'.