Get ready to REST

REST is one of those things in Software Developing that is simple to understand. However, people tend to misunderstand some details and keep doing it just because they don’t get compile or interpreting errors. But once this work is successfully done, it will be a wonderful thing to look at.

This web service opens your server application for external interaction. For instance, Twitter has a Rest API. This way, other developers can produce some third-party applications that, for example, can show you your tweets, like Tweetbot.

Rest uses the already existing HTTP protocol to achieve this. Actually, you don’t have to know much else, if you are already familiar how the most famous internet protocol works. But, for this to work your app has to have some web module listening on port 80 (HTTP), so it would be able to receive external requests from clients.


Disclaimer
All the following examples are adapted from Medium API. They might not represent the real API. If you want to consume the Medium API properly, you should read its documentation at https://developers.medium.com.

So lets start this off by looking at a REST request and response.

Request:

GET api.medium.com/v1/me HTTP/1.1
Host: api.medium.com
Authorization: Bearer 181d415f34379af07b2c11d144dfbe35d
Content-Type: application/json
Accept: application/json

Response:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
"data": {
"id": "5303d74c64f66366f00cb9b2a94f3251bf5",
"username": "majelbstoat",
"name": "Jamie Talbot",
"url": "https://medium.com/@majelbstoat",
"imageUrl": "https://images.medium.com/0*fkfQiTzT7TlUGGyI.png"
}
}

There are several things to understand here.

Every http request has this first line composed by a verb, the URL of the resource, the client wants to access, and the version of the HTTP protocol that is being used.

Verbs

GET

Use it for getting resources from the web app (e.g. getting all the stories of your publication).

POST

Use it for creating new resources on the web app (e.g. posting a new story).

PUT

Use it for updating resources on the web app (e.g. correcting a typo in your latest story).

DELETE

Use it for deleting resources on the web app (e.g. deleting a story).

The verb is the action you want to perform upon some resource. On the previous HTTP request you can see that Jamie is getting his profile data.

GET api.medium.com/v1/me .

For instance, if Medium allowed you to easily delete your profile through the API, you could request it by only changing the verb to DELETE.

DELETE api.medium.com/v1/me

Beginners on REST usually think of the URL as a method in some programming language and do things like these:

GET api.medium.com/v1/getProfile
GET api.medium.com/v1/removeProfile
POST api.medium.com/v1/updateProfile

These couldn’t be more wrong.

Even though, you could get away with this. You will eventually hit a wall down the road and the folks who are going to use your API will be your worst enemies. If you forbid yourself from using verbs in the URL and only use resource names, you’ll be all good. (I always knew that I could use those grammar lessons from the high school)

But what if you have a resource inside another resource? Well… You keep adding that up:

GET api.medium.com/v1/publications/1234/posts

In most cases, you won’t need more than two levels. If you do need it, think twice.

GET api.medium.com/v1/publications/1234/posts/{postId}/responses

This can be rewritten as follows.

GET api.medium.com/v1/posts/{postId}/responses

Authorization

Most of the requests you make to an API are somehow authenticated. This is needed so you can live in a stateless world where everything is much simpler on my humble opinion. Wonder how Jamie was able to retrieve its profile data? He needed to tell the server who he was. So he added this header:

Authorization: Bearer 181d415f34379af07b2c11d144dfbe35d

The ugly hieroglyph that follows the semicolon is the name he is known for by Medium. Most of the times you can get this secret token from the developers page.

Everything that needs some proof that you are who you say you are, you usually need to include a secret token.

Versioning

GET api.medium.com/v1/me

Curious about what is that ‘v1’ for? That’s the version of the API.

Imagine that you have to upgrade your API. You would want to give some time to the developers to migrate their applications to the latest one.

Parameters

What you know so far, will be enough for you to do some getting and deleting here and there. However, sometimes you need to add additional information, so you’d be able to get or delete specific resources, or even creating and editing new ones. You have two ways of doing this. Either by writing this extra information directly in the URL (query parameters) or on the http-request body. Each of them suits different needs as you‘re about to see.

Query parameters

Let’s revisit the example that retrieves some publication’s posts. To retrieve all the post from publication with ID 1234, you would have the following.

GET api.medium.com/v1/publications/1234/posts

What if you wanted to get only 5 posts of the total amount of stories that this publication has? You need to pass this argument somehow. With query parameters it will look like this.

GET api.medium.com/v1/publications/1234/posts?count=5

So as you can see, you add query arguments after a question mark ‘?’. You start off by naming the parameter and then attribute a value.

Do you want to pass more arguments? No problem. You separate them with a ‘&’.

GET api.medium.com/v1/publications/1234/posts?count=5&since=3

Body parameters

Now. Imagine you wanted to sign in your service. Do you think that it would be wise to pass a password all exposed in the URL? Even though, you would probably not use a browser to make requests to a REST API, is quite common that the URL will be write down in some logging tool on the target web server for further analysis. You would not want an IT guy snooping your deepest secrets!

If you wanted to create a post on Medium, you would need to tell the server to be prepared for receiving a JSON payload. Additionally, if you’re using a JSON friendly language like Python, you virtually could pass your object with little to none transformations.

POST /v1/users/5303d74c64f66366f00cb9b2a94f3251bf5/posts HTTP/1.1
Host: api.medium.com
Authorization: Bearer 181d415f34379af07b2c11d144dfbe35d
Content-Type: application/json
Accept: application/json
Accept-Charset: utf-8

{
"title": "Liverpool FC",
"contentFormat": "html",
"content": "<h1>Liverpool FC</h1><p>You’ll never walk alone.</p>",
"canonicalUrl": "http://jamietalbot.com/posts/liverpool-fc",
"tags": ["football", "sport", "Liverpool"],
"publishStatus": "public"
}

A good rule of thumb between using query parameters or body parameters is to look at the verb. If the verb is GET or DELETE use query parameters. Otherwise, use body parameters.

Responses

A HTTP response is composed by a status line (with a status code), response headers and payload.

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
"data": {
"id": "5303d74c64f66366f00cb9b2a94f3251bf5",
"username": "majelbstoat",
"name": "Jamie Talbot",
"url": "https://medium.com/@majelbstoat",
"imageUrl": "https://images.medium.com/0*fkfQiTzT7TlUGGyI.png"
}
}

Status

HTTP/1.1 200 OK
(...)

The status line tell us how well the server has interpreted our request. Below you can see the most common status code and their meaning. These are probably the ones that you’ll ever need to design your REST API.

  • 200 OK
  • 400 Bad Request
  • 401 Unauthorised
  • 403 Forbidden
  • 404 Not Found
  • 500 Server Error

I think they are all self-explaining and you actually can use whichever you like to best describe the status of the response. However, many developers misunderstand the difference between the 401 and the 403. The status 401 Unauthorised usually means you hadn’t attached a secret token, which the server needed to authenticate you for that specific request. The 403 Forbidden means that you’d successfully authenticated against the server, but for some reason you didn’t have enough privileges to access the resources you asked for.

Response payload

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
"data": {
"id": "5303d74c64f66366f00cb9b2a94f3251bf5",
"username": "majelbstoat",
"name": "Jamie Talbot",
"url": "https://medium.com/@majelbstoat",
"imageUrl": "https://images.medium.com/0*fkfQiTzT7TlUGGyI.png"
}
}

The response payload’s purpose is to return data to the client. Notice the “Content-Type” header telling that the data format of the response payload is JSON, in this case.


What’s next?

You just got an overview of REST interfaces and how to design an API properly with it. In the future, I might publish a more practical article about how to implement a REST API, for instance using Flask, a simple python web framework. Stay tuned!