In RESTful protocols, HTTP methods correspond to actions on a resource. Most commonly the four HTTP methods PUT, GET, POST, and DELETE are used to implement CRUD actions.

PUT vs. POST

People often mistakenly equate POST with Update and PUT with Create. For an exact definition, check the HTTP 1.1 RFC, but generally speaking...

PUT means "Create or update". It is assumed that the client knows the URI it wants to create. If a resource already exists at that location, it would be overwritten. It is similar to copying or moving a file to a location on Unix; if a file already exists there, it is overwritten. As an example, a client might want to send the request to create a record numbered "12345":

PUT /records/12345 HTTP/1.1
User-Agent: Client 2.0
Host: someserver.com
Content-Length: 15

...some data...

POST is intended as an "everything else" method. You might use POST to create, or you might use POST to update, or you might use POST to calculate some value. If a client is using it to create a new record, it wouldn't know the URI that would be created. A POST request's headers might look like this:

POST /records/ HTTP/1.1
User-Agent: Client 2.0
Host: someserver.com
Content-Length: 15

...some data...

In math, there's a concept of idempotence. A function (method) is idempotent if doing it once is the same as doing it twice is the same as doing it any number of times. This is analogous to painting a canvas blue. If you've done it once, it's blue. If you've done it twice, it's still blue.

PUT should be idempotent, while POST should not. If a client were to keep POSTing as in the request above, every POST would create a new record.

Fake PUT and DELETE

At some point in testing, it will probably occur to you to use an HTML form to test how your server behaves to different requests methods. Unfortunately, HTML forms only accept GET and POST as values for method. Any other values are undefined. If you overload the POST method to read in a parameter called "_method", you can get around this limitation.

<form method="POST" action="records/?_method=PUT">