REST APIs in Plain English

Máté Safranka
8 min readJan 7, 2019

--

Confession time: for the first two years of my career, REST API was one of those “smile and nod” terms I hoped I’d just figure out along the way. The concept is so ubiquitous in web development nowadays, it’s one of those things everyone assumes you already know, like how to use git. So, for all the Andy Dwyers out there who at this point are too afraid to ask, here’s a little help.

In the previous two articles, we went over layers of abstraction and HTTP. Today, we’ll be looking at how these two come together to create a unified and efficient paradigm for developing web apps for both the front- and backend.

But first, a little history lesson.

Simple Times

Have you ever wondered why URL’s look so similar to file paths on your computer? It’s because originally, that’s exactly what they were. The term URL stands for Uniform Resource Locator; it was a special kind of file path that could describe the location of any file on any computer that was published on the web.

Websites at the time consisted of completely static pages. Each page had to be a separate file, and their content only changed when someone manually changed the file itself. Browsers, respectively, were pretty much only capable of displaying text and images; browsing the web was basically like looking at Word documents on someone else’s computer.

The first major change was the adoption of HTTP POST.

HTTP requests have an attribute we haven’t discussed in the previous article: the method. You may recall that, when a server responds to a request, it stamps a status code on the response to give a general indication of its contents: 200 for success, 404 if the file was not found, 500 for miscellaneous errors, etc. The method is sort of similar: it’s stamped on the request by the client, as a general indication of its intent.

Unlike the status code, the method is not a number, but an English word. In the early days of the web, this word would be one of two: GET or POST.

  • Sending a GET request to a URL meant “Give me the contents of this file”, which is the process we’re already familiar with.
  • Sending a POST request to a URL meant “Run this program and send me the results.” As you can expect, the URL in this case was supposed to point to a program on the server, instead of an HTML or image file. POST requests can contain arbitrary data, called the body or payload, which is provided to the program as input.

This allowed websites to become interactive to a certain degree. The user could fill out a form, the browser sent the details to a server via HTTP POST, a program on the server processed the data, and generated an HTML page as a result.

Developers soon realized that GET requests could just as well be directed at programs instead of static HTML files. This resulted in dynamic pages that could display varying content on every page load, without anyone having to change any files.

HTTP POST gave rise to the first online stores and forums — precursors to modern-day sites such as Reddit or StackOverflow — and dynamic page generation allowed news sites to update their contents multiple times a day with minimal effort.

Less Simple Times

The next big step came when web servers added a feature called URL rewriting. When a request came in for a file that didn’t exist, instead of immediately rejecting it with a 404 status code, the server could now run a small program that would take the invalid URL, and attempt to turn it into a valid one.

For example, let’s say you had a program on your server example.com called cgi-bin/article.cgi, which could load an article from the database and return it to the client as an HTML page. Normally, you would have to access this page via something similar (assuming the database ID of the article is 12345678):

http://www.example.com/cgi-bin/article.cgi?article_id=12345678

A URL like this is long, ugly, and prone to typos or copy-paste errors. It would be much nicer to be able to type this into your browser:

http://www.example.com/article/12345678

Normally, this URL would imply that there’s a folder called article on your server, with a file named 12345678 inside, which of course we know there isn’t. URL rewriting allows us to tell the server that if a URL follows the pattern /article/<article-id> , then it should behave as if the request was for /cgi-bin/article.cgi?article_id=<article_id> and run the program article.cgi with the supplied article ID as the input.

URL rewriting had no direct effect on browsers. The process takes place entirely on the server; the browser has no way of knowing if the URL they’re sending the request to is an actual file, or if it will be rewritten to run a program.

On a grander scale, however, it did transform the way browsers and servers talked to each other. Instead of pointers to static files, URL’s became instructions that frontend developers could send to the server to perform a wide variety of tasks. Websites matured into fully-featured web apps.

If you remember our taxi article, this might ring a bell. A program publishes simplified instructions that allow clients to perform complex operations — doesn’t that sound like an interface?

And you would be exactly right. More specifically, it’s an example of what we call an Application Programming Interface, or API. Normally, when we talk about interfaces, we refer to different parts of the same program; an API is how a complete program can allow other programs to communicate with it.

In our case, the program on the server (the backend) can define a set of URL’s, to which the program in the browser (the frontend) can send HTTP requests as instructions. The developers on the two ends just need to agree what those instructions are. And if there’s one thing developers are good at, it’s agreeing on things.

…Right?

Increasingly Confusing Times

Imagine, if you will, that you are a frontend developer, and you get a project to make a calendar app for a client. Another company has already gotten started on the backend development, so you contact them to find out what HTTP requests you need to make in order to fetch, create, and delete calendar entries. They give you the following list:

  • To get calendar entries, send HTTP POST to /calendar/entries/get.
  • To create a calendar entry, send HTTP POST to /calendar/entries/create, and include the entry details in JSON.
  • To delete a calendar entry, send HTTP POST to /calendar/entries/delete, and send a JSON object with a single id key, whose value is the entry ID to be deleted.

Fair enough. You build the frontend, you test extensively, everything works, everyone’s happy. Then, a few months later, you get a project to make a calendar app for a different client. Once again, the client had another company do the backend development, and they give you this API:

  • To get calendar entries, send HTTP GET to /calendar/loadentries.
  • To create a calendar entry, send HTTP POST to /calendar/newentry, and include the entry details as an XML document in the payload.
  • To delete a calendar entry, send HTTP POST to /calendar/deleteentry?id=<entry_id>, where <entry_id> is the ID of the entry to be deleted.

Basically, nothing you built for the previous app can be reused, as far as backend communication goes. Now imagine this chaos on an industry-wide scale.

Arguably the most relatable reaction image for developers. (Dan Olson, “A Christmas Story: A Tale of Technological Nostalgia”)

The need for some degree of standardization became abundantly clear.

And the Rest is History

REST, short for Representational State Transfer, is a comprehensive network-based architectural style. As you may have guessed from the amount of big words in that description, it is a much deeper and broader subject than one entry-level article can cover. For our purposes, it’s enough if we discuss how it regulates communication in web services.

The first main effort is redefining URL’s. In a modern web app, we no longer just read static documents; we view and manipulate various types of content. Blog entries, comments, notifications, images, albums, etc. These bits of content are almost always stored in a database, and marked with a unique ID. URL’s in a REST API can either refer to a type of content, or a specific item, and they must adhere to the following patterns:

  • /<type> to access the entire collection of a type of content
  • /<type>/<id> to access a specific item of that type

For example, /article/12345678 allows us to do something with the article whose ID is 12345678. The URL /article, in turn, means we want to do something with the entire collection of articles, such as run a search query.

These kinds of URL’s are more commonly called Uniform Resource Identifiers, or URI’s. The distinction in name makes it clear that it’s not supposed to point at an actual file on a computer, but rather an abstract item; it is up to the program to determine exactly how to fetch the contents.

This is all well and good, but how do we indicate what we want to do with article 12345678? This is where the second half of the REST standard comes in, which is about methods.

HTTP defines a variety of methods besides GET and POST, and browsers have always been capable of using them (since it’s literally just a matter of stamping a different word at the beginning of the request), they just weren’t necessary before. Two of these methods are PUT and DELETE, which were included in REST to create the following array of instructions:

  • GET /type: Get all items of a type, or run a search
  • POST /type: Create a new item of a type.
  • GET /type/id: Get a specific item of a type.
  • PUT /type/id: Update an existing item of a type.
  • DELETE /type/id: Delete an existing item of a type.

In the case of POST and PUT requests, the payload is the contents of the new or updated item. REST doesn’t define any particular format, but the industry has largely adopted JSON as the default.

(Note: REST defines other method + URI combinations as well, but those are very rarely used. You can read more in the Wikipedia article)

The greatest advantage of REST is that of any other standard: it reduces the time and effort needed to develop an API, and increases the reusability of code between apps. The unified format of URI’s also opened up the door for all sorts of automation, such as generating and updating documentation of the available instructions. The URI + method combinations are fairly intuitive, and the URI patterns are open-ended, allowing backend developers to add custom actions for various types of content if necessary.

Hopefully this has given you an idea of web services in general, and REST in particular. Like I said, this is only a cursory glance into a very deep subject, and I encourage you to do some further research if you’re at all interested. It took the industry a few years of grief, but eventually we got a widely adopted and easy-to-use paradigm for communication.

Now all that’s left is to go through the same with WebSockets.

Mate Safranka is a frontend developer at Supercharge. Besides the articles he’s already plugged in this one, he also had some thoughts about making in-app navigation less of a nightmare (for developers).

--

--

Máté Safranka

Frontend developer, learning confectioner, hobbyist game maker, amateur writer.