--- 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 %}