| 1 | 1 | new file mode 100644 | 
| ... | ... | @@ -0,0 +1,154 @@ | 
| 0 | +--- | |
| 1 | +layout: post | |
| 2 | +title: "A quick look at REST" | |
| 3 | +date: 2013-10-06 14:27 | |
| 4 | +comments: true | |
| 5 | +categories: [server, shell, webdev] | |
| 6 | +cover: /images/cover/avatar.png | |
| 7 | +keywords: rest, restful, Representational State Transfer, crud, api, post, get, put, delete | |
| 8 | +description: An intro to REST | |
| 9 | +--- | |
| 10 | + | |
| 11 | +Three months ago I've chosen a | |
| 12 | +[REST](http://en.wikipedia.org/wiki/Representational_state_transfer) | |
| 13 | +architecture for designing my new project at work. The project goal is to create | |
| 14 | +<abbr title="Application Programming Interface">API</abbr> for managing gyms, | |
| 15 | +trainings and trainees. | |
| 16 | + | |
| 17 | +This article is just light intro to the REST world, don't expect cool tips & | |
| 18 | +tricks (maybe in next article). | |
| 19 | + | |
| 20 | +# HTTP request methods | |
| 21 | + | |
| 22 | +REST without using proper [HTTP methods](http://en.wikipedia.org/wiki/ | |
| 23 | +Hypertext_Transfer_Protocol#Request_methods) is a nonsense. There are about 9 | |
| 24 | +methods but we need only 4. | |
| 25 | + | |
| 26 | +* ```POST``` -- create a new resource | |
| 27 | +* ```GET``` -- get resource data | |
| 28 | +* ```PUT``` -- update a resource | |
| 29 | +* ```DELETE``` -- delete a resource | |
| 30 | + | |
| 31 | +There is also ```PATCH``` method which is very similar to ```PUT``` method. | |
| 32 | +In fact ```PUT``` should rewrite a whole resource and ```PATCH``` only update | |
| 33 | +some attributes of a resource. More about ```PUT``` vs ```PATCH``` | |
| 34 | +[here](https://restful-api-design.readthedocs.org/en/latest/methods.html#patch- | |
| 35 | +vs-put). | |
| 36 | + | |
| 37 | +<!-- more --> | |
| 38 | + | |
| 39 | +# Simple example (we always work with objects) | |
| 40 | + | |
| 41 | +REST greatly improves a simplicity of using the API. Let's have a look at an | |
| 42 | +example how we manage trainings: | |
| 43 | + | |
| 44 | + http://api.example.com/training/ | |
| 45 | + http://api.example.com/training/:training/ | |
| 46 | + | |
| 47 | +We can access that URLs via ```GET```, ```POST```, ```PUT``` or ```DELETE``` | |
| 48 | +HTTP methods. If we want | |
| 49 | +to create a new training then we call the first URL. If we want to read | |
| 50 | +training data, or update data, or delete a training then we use the second URL | |
| 51 | +(just replace ```:training``` with some integer). Actually, REST force you take | |
| 52 | +an advantage of | |
| 53 | +[CRUD](http://en.wikipedia.org/wiki/Create,_read,_update_and_delete). And | |
| 54 | +that's good. As you can see, to make operations with trainings we need just two | |
| 55 | +URLs (I call them *access points*). | |
| 56 | + | |
| 57 | +The philosophy of REST is to access *objects*. In the example ```training``` | |
| 58 | +was the object. The reason is simple -- we can make CRUD operations (read, | |
| 59 | +write, update, delete) only with objects. | |
| 60 | + | |
| 61 | +# Another example | |
| 62 | + | |
| 63 | +Well, you can ask: "What if I need to tell a trainee X wants to join training | |
| 64 | +Y?". I solved the problem by creating another access point: | |
| 65 | + | |
| 66 | + http://api.example.com/training/:training/attendance/:trainee/ | |
| 67 | + | |
| 68 | +Now we are working with ```attendance``` object. Allowed HTTP methods for this | |
| 69 | +access point are PUT and DELETE. | |
| 70 | +If a trainee with ID 541 wants to join training with ID 1050 we call | |
| 71 | +```http://api.example.com/training/1050/attendance/541/``` with ```PUT``` | |
| 72 | +method. Later the trainee changes his mind and wants to leave the training, so | |
| 73 | +we call the same URL with ```DELETE``` method. | |
| 74 | + | |
| 75 | +# How to send data to server with cURL | |
| 76 | + | |
| 77 | +I'll illustrate using REST API with curl utility. | |
| 78 | + | |
| 79 | +## POST method: | |
| 80 | + | |
| 81 | +Let's create a new training: | |
| 82 | + | |
| 83 | +{% codeblock lang:bash %} | |
| 84 | + curl -X POST \ | |
| 85 | + --data-urlencode "starts_at=2013-12-12 12:00" \ | |
| 86 | + --data-urlencode "ends_at=2013-12-12 13:00" \ | |
| 87 | + --data-urlencode "name=New training" \ | |
| 88 | + http://api.example.com/training/ | |
| 89 | +{% endcodeblock %} | |
| 90 | + | |
| 91 | +A simplified server response can look like this (in JSON): | |
| 92 | + | |
| 93 | +{% codeblock lang:json %} | |
| 94 | +{ | |
| 95 | + "id" : 800, | |
| 96 | + "name" : "New training", | |
| 97 | + "starts_at" : "2013-12-12T12:00:00+0100", | |
| 98 | + "ends_at" : "2013-12-12T13:00:00+0100", | |
| 99 | + "created_at" : "2013-10-06T17:23:12+0200", | |
| 100 | + "updated_at" : "2013-10-06T17:23:12+0200" | |
| 101 | +} | |
| 102 | +{% endcodeblock %} | |
| 103 | + | |
| 104 | +## GET method: | |
| 105 | + | |
| 106 | +Now we know training ID. Getting information about training: | |
| 107 | + | |
| 108 | +{% codeblock lang:bash %} | |
| 109 | + curl http://api.example.com/training/123/ | |
| 110 | +{% endcodeblock %} | |
| 111 | + | |
| 112 | +We haven't changed training data so a server response looks exactly like in | |
| 113 | +above example. | |
| 114 | + | |
| 115 | +## PUT method: | |
| 116 | + | |
| 117 | +I made a mistake! The training should ends at 13:30, let's change it: | |
| 118 | + | |
| 119 | +{% codeblock lang:bash %}  | |
| 120 | + curl -X PUT \ | |
| 121 | + --data-urlencode "ends_at=2013-12-12 13:30" \ | |
| 122 | + http://api.example.com/training/800/ | |
| 123 | +{% endcodeblock %} | |
| 124 | + | |
| 125 | +A simplified server response: | |
| 126 | + | |
| 127 | +{% codeblock lang:json %} | |
| 128 | +{ | |
| 129 | + "id" : 800, | |
| 130 | + "name" : "New training", | |
| 131 | + "starts_at" : "2013-12-12T12:00:00+0100", | |
| 132 | + "ends_at" : "2013-12-12T13:30:00+0100", | |
| 133 | + "created_at" : "2013-10-06T17:23:12+0200", | |
| 134 | + "updated_at" : "2013-10-06T17:32:11+0200" | |
| 135 | +} | |
| 136 | +{% endcodeblock %} | |
| 137 | + | |
| 138 | +## DELETE method: | |
| 139 | + | |
| 140 | +This deletes training: | |
| 141 | + | |
| 142 | +{% codeblock lang:bash %} | |
| 143 | + curl -X DELETE \ | |
| 144 | + http://api.example.com/training/800/ | |
| 145 | +{% endcodeblock %} | |
| 146 | + | |
| 147 | +An obligatory server response: | |
| 148 | + | |
| 149 | +{% codeblock lang:json %} | |
| 150 | +{ | |
| 151 | + "success" : true | |
| 152 | +} | |
| 153 | +{% endcodeblock %} |