loading...

Explain HTTP Verbs like I'm Five

Pratik Ambani on October 14, 2017

markdown guide
 

When you are playing with your toys you can:
GET your toys from the shelves
PUT new paint on them when they scratch
POST a new toy on the shelf to brag
DELETE them to the garbage when they are broken and old

As a 5y old you should focus on the new REST evolution like GraphQL because when you'll grow up you'll work with them (see JSON vs XML).

 

It was quite easy to understand buddy, but what about patch?

 

I never saw a REST implementation to differentiate the PATCH vs PUT. In most real world examples you will use only GET and POST, it's best for everyone to have fewer endpoints and commands. If the POST has an UUID then is an update (PATCH), and PUT you almost never want/need it, because you don't want to carry around the entire records,only the fields you are interested in.

In order to differentiate between the POST/PUT/PATCH you have to know the state of the record, and it's hard to do in a distributed system, in a app that the user can be logged in from multiple devices in the same time, etc etc.

Anyway I'll try to remix it

PATCH - new paint only on the part it was scratched
PUT - new paint on the entire toy, even if it had a small scratch. If you want to keep the "good" scratches that you are bond to (for melancholic reasons) you have to recreate them.

 

Rule 1: Very few people actually know the rules

The most important thing to know about using HTTP in practice is that it is like the board game Monopoly: it comes with a very specific book of rules that almost nobody follows completely. There are some rules in Monopoly that most people follow, like how you roll the dice and go around the board, but a lot of details are simply made up. For example, in most households there will be some reward ($500 or more) for landing on the "Free Parking" space. The rules say that nothing happens when you land there, but no one follows the actual rules.

HTTP verbs are governed by the official "rule books" RFC7231-sec4.3 and RFC5789.

Now part of the reason that no one completely follows the rules is likely laziness on the part of API developers, but another important reason is that they don't really apply terribly well for a lot of things that people want to do. This is similar to Monopoly, where people really just want to have fun. Getting $500 when you land on "Free Parking" is much more exciting than nothing happening, so even if you tell people what the rule says they should do, they won't follow it.

There are two rules about HTTP verbs that are almost universally followed in my experience, they are good rules, and make sense in nearly any context:

  • GET - this only retrieves information and doesn't change anything on the server. It's completely safe to GET and you shouldn't ever break anything by doing so. In terms of "look, but don't touch", a GET request is just looking.
  • POST - this typically can and will cause changes to happen. In the "look, but don't touch" adage, with a POST you are touching.

Rule 2: The rules are rules for managing documents

The rest of the rules don't always make much sense because people tend to use HTTP for things it wasn't originally intended to do. The point of HTTP is to publish hypertext documents and send them around the network. So the rules talk about "resources" which if you aren't shipping around documents doesn't always make a whole lot of sense. I think this is really why the verb meanings seem more confusing than they are.

So in order to understand the rules, lets take a JSON grocery list: {"groceries": ["milk", "eggs", "apples"]}. Think of this as your document, published at the URL http://www.myserver.foo/grocery_list.json.

  • A GET to http://www.myserver.foo/grocery_list.json will retrieve the document {"groceries": ["milk", "eggs", "apples"]}, and give you a status code of 200 (meaning OK), along with some header information such as the content-type which is json.
  • A HEAD to http://www.myserver.foo/grocery_list.json will give you the status code and header information that a GET would have provided, telling you that the document exists and has a type of json, but doesn't send the actual document.
  • A PUT to http://www.myserver.foo/grocery_list.json will replace your grocery list with the document you send in the request body. For example, if I PUT {"groceries": ["grapes", "bananas"]}, then the next time someone does a GET, they will get my new list {"groceries": ["grapes", "bananas"]} back. The contents of the document are completely replaced. I can update an existing document like this or even create a new one if the server allows it.
  • A DELETE to http://www.myserver.foo/grocery_list.json removes the document. A subsequent GET request will return a status code of 404 NOT FOUND.

Now for the POST command, what it does depends on the additional rules that my server and API allows. For example, my grocery list API might allow you to post a JSON body of {"add": "food-item"} or {"remove": "food-item"} to update the existing list. So with these rules I could do the following:

  • A POST to http://www.myserver.foo/grocery_list.json with a body of {"add": "bananas"} would modify the document so that a subsequent GET would then return {"groceries": ["milk", "eggs", "apples", "bananas"]}.

Note that a POST can also modify multiple documents, not just the one specified by the URL. Sometimes a POST can be used to bulk modify, create, or delete multiple documents in a single request.

There are other methods, but those are the most common in my experience. If you think in terms of a url pointing to a document called a "resource", then you can make better sense of the RFCs.

Rule 3: Everyone tends to make up a few of their own rules

I think HTTP is a nice and extremely convenient protocol, which along with the popularity of web browsers has led to it being used to do things other than manage documents. People write APIs to allow you to POST to do all sorts of things, like buy airplane tickets, or even image a new webserver. Its not always easy to think about these remote procedures in terms of "documents" so the rules get muddled, and often only GET and POST gets used in a meaningful way.

As a result of the popularity of HTTP in doing things other than transporting documents, people tend to not follow the rules even when they are transporting documents. I see a lot of "house rules" in HTTP APIs where PUT is used to create a document, and POST to update a document (or maybe the other way around), even though PUT is really for when you are sending the entire document, and POST is for when you are sending instructions for modification. The best thing to do is read the API you are using. If designing an API, I think it makes sense to try to follow the actual RFC rules as best as possible. The more you follow the HTTP specification, the more clients will be able to understand your API without having to read lengthy documentation.

If the verbs don't make any sense for what you are doing when designing an API, you can always use GET to retrieve information, POST to make changes, and document carefully how they work in your API.

 

HTTP verbs best thought of as tools to manage documents...

So does that make the RESTful approach a practice for using HTTP verbs to manage those documents ?

 

Keep in mind that all of the previous answers refer to the commonly-accepted spec for REST and its relatives. But a web server can respond however it wants to any call it wants; HTTP calls are received in plain text and the server can choose to interpret and use (or completely ignore) the verb. None of this is inherent to HTTP calls, it's just a norm that most APIs choose to follow.

 

This is a really good point to make. When I was learning about REST the first time, I was told what the different verbs do. I was a little confused and trying to figure out how it was enforced programmatically, only to find out that it wasn't. You could technically create things with GET, it's just bad/unconventional API design.

 

You can think of URLs as markers of cabinets and shelves in a big set of cabinets.

GET means: Fetch me the thing in the place where the URL points. GET /widgets tells me I want to access all the items in the cabinet where widgets are stored. GET /widgets/5 tells me I want the widget on shelf #5 in the cabinet. (There may be a lot of shelves in the cabinet!)

POST means: Add a new shelf with a new thing in this cabinet. For example, POST /widgets means add a thing to the widgets cabinet.

PUT means: Replace a thing in this cabinet. For example, PUT /widgets/5 means replace the thing on widget shelf #5 with this new thing I'm sending you.

PATCH means: Make some changes to a thing in this cabinet. PATCH /widgets/5 means "Here's a set of changes to make to the widget on shelf #5." There's no standard way of describing those changes.

DELETE means: Remove a thing from the cabinet. For example, DELETE /widgets/5 means throw out whatever is on shelf #5 in the widgets cabinet.

 

This should be easy to explain, but honestly, I never used anything but GET and POST until recently, because until AJAX and REST APIs came to the fore, it didn't make sense. I mean, you wouldn't want just anyone to modify or delete your pages, right?

GET is the most common one. You want a page/image/library/video/feed/whatever, it gets it. I don't know if this is RFC-specific or just part of Apache, but you can only use QUERY_STRING with this verb. This allows you have Next link to http://example.com/?page=2, which can (and did) easily get unmanageable as options grew.

POST in the old way allowed you to send the query without having an excessively large query string in the URL. In the post-REST world, the best way to think of POST is as the CREATE of CRUD interaction, as GET is READ.

DELETE is DELETE in CRUD. Whatever you're referencing, remove it, even if that's just setting a 'deleted' flag for the entry in the database entry.

And finally, PUT is the equivalent to CRUD's UPDATE, where it takes the input as changes.

The source I love for diving more deeply into creating REST APIs is Build APIs You Won't Hate by Phil Sturgeon. The example code on Github is Laravel-centric, but the text is not, which makes it easily adaptable to whatever environment you find yourself in.

 
code of conduct - report abuse