--- 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 API 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). # 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 %}