---
layout: post
title: "A quick look at REST"
date: 2013-10-06 14:27
comments: true
categories: [server, shell, webdev]
cover: /images/cover/avatar.png
keywords: rest, restful, Representational State Transfer, crud, api, post, get, put, delete
description: An intro to REST
---

Three months ago I've chosen a 
[REST](http://en.wikipedia.org/wiki/Representational_state_transfer) 
architecture for designing my new project at work. The project goal is to create 
<abbr title="Application Programming Interface">API</abbr> for managing gyms, 
trainings and trainees. 

This article is just light intro to the REST world, don't expect cool tips & 
tricks (maybe in next article).

# HTTP request methods

REST without using proper [HTTP methods](http://en.wikipedia.org/wiki/
Hypertext_Transfer_Protocol#Request_methods) is a nonsense. There are about 9 
methods but we need only 4.

* ```POST``` -- create a new resource
* ```GET``` -- get resource data
* ```PUT``` -- update a resource
* ```DELETE``` -- delete a resource

There is also ```PATCH``` method which is very similar to ```PUT``` method.
In fact ```PUT``` should rewrite a whole resource and ```PATCH``` only update 
some attributes of a resource. More about ```PUT``` vs ```PATCH```
[here](https://restful-api-design.readthedocs.org/en/latest/methods.html#patch-
vs-put).

<!-- more -->

# Simple example (we always work with objects)

REST greatly improves a simplicity of using the API. Let's have a look at an 
example how we manage trainings:

	http://api.example.com/training/
	http://api.example.com/training/:training/

We can access that URLs via ```GET```, ```POST```, ```PUT``` or ```DELETE``` 
HTTP methods. If we want 
to create a new training then we call the first URL. If we want to read 
training data, or update data, or delete a training then we use the second URL 
(just replace ```:training``` with some integer). Actually, REST force you take 
an advantage of 
[CRUD](http://en.wikipedia.org/wiki/Create,_read,_update_and_delete). And 
that's good. As you can see, to make operations with trainings we need just two 
URLs (I call them *access points*).

The philosophy of REST is to access *objects*. In the example ```training``` 
was the object. The reason is simple -- we can make CRUD operations (read, 
write, update, delete) only with objects.

# Another example

Well, you can ask: "What if I need to tell a trainee X wants to join training 
Y?". I solved the problem by creating another access point:

	http://api.example.com/training/:training/attendance/:trainee/

Now we are working with ```attendance``` object. Allowed HTTP methods for this 
access point are PUT and DELETE. 
If a trainee with ID 541 wants to join training with ID 1050 we call 
```http://api.example.com/training/1050/attendance/541/``` with ```PUT``` 
method. Later the trainee changes his mind and wants to leave the training, so 
we call the same URL with ```DELETE``` method.

# How to send data to server with cURL

I'll illustrate using REST API with curl utility.

## POST method:
 
Let's create a new training:

{% codeblock lang:bash %}
	curl -X POST \
		--data-urlencode "starts_at=2013-12-12 12:00" \
		--data-urlencode "ends_at=2013-12-12 13:00" \
		--data-urlencode "name=New training" \
		http://api.example.com/training/
{% endcodeblock %}

A simplified server response can look like this (in JSON):

{% codeblock lang:json %}
{
	"id"             : 800,
	"name"           : "New training",
	"starts_at"      : "2013-12-12T12:00:00+0100",
	"ends_at"        : "2013-12-12T13:00:00+0100",
	"created_at"     : "2013-10-06T17:23:12+0200",
	"updated_at"     : "2013-10-06T17:23:12+0200"
}
{% endcodeblock %}

## GET method:
 
Now we know training ID. Getting information about training:

{% codeblock lang:bash %}
	curl http://api.example.com/training/123/
{% endcodeblock %}

We haven't changed training data so a server response looks exactly like in 
above example.

## PUT method:
 
I made a mistake! The training should ends at 13:30, let's change it:
 
{% codeblock lang:bash %} 
	curl -X PUT \
		--data-urlencode "ends_at=2013-12-12 13:30" \
		http://api.example.com/training/800/
{% endcodeblock %}

A simplified server response:

{% codeblock lang:json %}
{
	"id"             : 800,
	"name"           : "New training",
	"starts_at"      : "2013-12-12T12:00:00+0100",
	"ends_at"        : "2013-12-12T13:30:00+0100",
	"created_at"     : "2013-10-06T17:23:12+0200",
	"updated_at"     : "2013-10-06T17:32:11+0200"
}
{% endcodeblock %}

## DELETE method:

This deletes training:

{% codeblock lang:bash %}
	curl -X DELETE \
		http://api.example.com/training/800/
{% endcodeblock %}

An obligatory server response:

{% codeblock lang:json %}
{
	"success" : true
}
{% endcodeblock %}

*This article was also published on my school [blog](http://cinan.blog.matfyz.sk/p94260)*.