{"id":218,"date":"2016-06-26T12:18:49","date_gmt":"2016-06-26T10:18:49","guid":{"rendered":"http:\/\/localhost:8888\/wordpress\/?p=218"},"modified":"2016-09-18T18:10:58","modified_gmt":"2016-09-18T16:10:58","slug":"rest-palvelun-pystytys","status":"publish","type":"post","link":"https:\/\/www.pilvikoodari.net\/?p=218","title":{"rendered":"REST palvelun pystytys"},"content":{"rendered":"<p><strong>Yleist\u00e4 RESTist\u00e4<\/strong><\/p>\n<p>REST-palvelu on yleinen tapa toteuttaa tietopalvelun rajapinta web-palvelulle. REST-palvelu on ulosp\u00e4in itse asiassa kuin &#8221;perinteinen&#8221; HTTP-palvelu ja REST-rajapinta vastaa samoihin pyynt\u00f6ihin kuin perus HTTP-palvelin. My\u00f6s HTTP -statuskoodit ovat k\u00e4yt\u00f6ss\u00e4 eli onnistunut REST-palvelupyynn\u00f6n k\u00e4sittely palauttaa statuskoodin <strong>200 OK<\/strong>, ep\u00e4onnistunut tiedonhaku (vaikkapa haku\u00a0id:ll\u00e4 jota ei l\u00f6ydy tietokannasta) palauttaa statuskoodin <strong>404\u00a0 Not found<\/strong>, jne.<\/p>\n<p>Erona perus HTTP-palvelimeen\/palveluun on, ett\u00e4 paluuviestin\u00e4 ei saada HTML-sivua vaan tyypillisesti JSON-muotoinen vastaus. Formaatti REST-palvelussa on tyypillisesti JSON mutta voisi olla\u00a0my\u00f6s XML. JSON on helposti hy\u00f6dynnett\u00e4viss\u00e4 JavaScriptiss\u00e4 ja se voidaan tallentaa ilman muunnosta suoraan no-sql tietokantaan (esim. MongoDB) joten se on k\u00e4tev\u00e4 ja suosittu formaatti.<\/p>\n<p><strong>REST verbit (=metodit)<\/strong><\/p>\n<p>Seuraavassa esitell\u00e4\u00e4n yleinen REST-palveluiden k\u00e4ytt\u00e4m\u00e4 HTTP-verbien k\u00e4ytt\u00f6tapa. Kyseess\u00e4 on siis yleinen k\u00e4yt\u00e4nt\u00f6, mutta ei tietenk\u00e4\u00e4n\u00a0pakollinen &#8221;sapluuna&#8221; vaan palvelun toteuttaja p\u00e4\u00e4tt\u00e4\u00e4 millaisella k\u00e4yt\u00e4nn\u00f6ll\u00e4 palvelua k\u00e4ytet\u00e4\u00e4n.<\/p>\n<p><strong>GET\u00a0\u00a0\u00a0 <\/strong>Tietopyynt\u00f6 jolla haetaan tallennettua dataa. Esimerkiksi pyynt\u00f6 <em>GET http:\/\/palvelu.net\/asiakkaat<\/em> palauttaa listan asiakkaista. Pyynn\u00f6ss\u00e4 voidaan my\u00f6s yksil\u00f6id\u00e4, mik\u00e4 datayksil\u00f6 halutaan hakea. Silloin osoitteeseen lis\u00e4t\u00e4\u00e4n haettavan tietueen id, esimerkiksi <em>GET http:\/\/palvelu.net\/asiakkaat\/f310e311-93e5-43ae-be0a-71628a147b90.<\/em><\/p>\n<p><strong>POST\u00a0\u00a0\u00a0\u00a0<\/strong> Tiedon tallennus. Esimerkiksi osoitteeseen <em>http:\/\/palvelu.net\/asiakkaat<\/em> postattu JSON muotoinen sis\u00e4lt\u00f6 <em>{&#8221;nimi&#8221;:&#8221;Aku Ankka&#8221;, &#8221;address&#8221;: &#8221;Paratiisitie 13&#8221;}<\/em> tallettaisi Aku Ankan asiakastietoihin. <strong>Paluuviestiss\u00e4<\/strong> <strong>saadaan tallennettu tietue varustettuna<\/strong> <strong>id:ll\u00e4, <\/strong>jos tallennus onnistui.<\/p>\n<p><strong>PUT\u00a0\u00a0\u00a0<\/strong> Tiedon p\u00e4ivitys eli update. Palvelupyynn\u00f6n mukana annetaan taas tiedot kuten POST-pyynn\u00f6ss\u00e4\u00a0mutta t\u00e4ll\u00e4 kertaa mukana on tietueen id, jotta p\u00e4ivitys osataan kohdistaa ko. riviin. Esim. <em>PUT http:\/\/palvelu.net\/asiakkaat\/f310e311-93e5-43ae-be0a-71628a147b90 <\/em>ja content osiossa tietueen tiedot <em>{&#8221;nimi&#8221;:&#8221;Aku Ankka&#8221;, &#8221;address&#8221;: &#8221;Hanhivaaranpolku 22&#8221;}<\/em>\u00a0.<\/p>\n<p><strong>DELETE\u00a0\u00a0\u00a0 <\/strong>Tiedon poisto. Luonnollisesti yleens\u00e4 j\u00e4rkev\u00e4 vain kun kohdistetaan tiettyyn tietoriviin, id:ll\u00e4 osoitettuna, esim. <i>DELETE http:\/\/palvelu.net\/asiakkaat\/f310e311-93e5-43ae-be0a-71628a147b90. <\/i>Mik\u00e4\u00e4n ei tietysti est\u00e4 toteuttamasta DELETE-operaatiota my\u00f6s osoitteelle<i> http:\/\/palvelu.net\/asiakkaat <\/i>siten ett\u00e4 pyynt\u00f6 poistaisi kaikki asiakastiedot, mutta t\u00e4m\u00e4 ei yleens\u00e4 liene kovin j\u00e4rkev\u00e4\u00e4.<\/p>\n<p>Muitakin HTTP-verbej\u00e4 voidaan k\u00e4ytt\u00e4\u00e4, mutta yll\u00e4 ehk\u00e4 t\u00e4rkeimm\u00e4t.<\/p>\n<p>Tarkemmin REST verbeist\u00e4 esim. t\u00e4\u00e4lt\u00e4:<\/p>\n<p><a href=\"http:\/\/www.restapitutorial.com\/lessons\/httpmethods.html\" target=\"_blank\">http:\/\/www.restapitutorial.com\/lessons\/httpmethods.html<\/a><\/p>\n<p><strong>REST palvelun testausty\u00f6kalu selaimeen<\/strong><\/p>\n<p>Olemassa olevia REST-palveluita on helpointa testata selaimeen asennetun POSTER-lis\u00e4osan avulla. Kun selaimeen asentaa POSTER lis\u00e4osan (t\u00e4ll\u00e4 nimell\u00e4 l\u00f6ytyy ainakin Firefoxiin ja Cromeen) niin selaimen valikosta saa k\u00e4tev\u00e4sti k\u00e4yntiin testerin jolla voi tehd\u00e4 pyynt\u00f6j\u00e4 REST-palveluihin ja tarkastella saatua vastausta. Alla kuva Firefoxissa toimivasta POSTER add-onista:<\/p>\n<p><a href=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/poster-1.jpg\" rel=\"attachment wp-att-237\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-237\" src=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/poster-1.jpg\" alt=\"poster\" width=\"400\" height=\"531\" srcset=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/poster-1.jpg 552w, https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/poster-1-226x300.jpg 226w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/a><\/p>\n<p>Posterilla on helppo l\u00e4hett\u00e4\u00e4 REST-palveluun erityyppisi\u00e4 pyynt\u00f6j\u00e4 ja katsoa mit\u00e4 tulee vastaukseksi.<\/p>\n<p>Latauslinkki : POSTER AddOn for Firefox:<\/p>\n<p><a href=\"https:\/\/addons.mozilla.org\/en-US\/firefox\/addon\/poster\/\" target=\"_blank\">https:\/\/addons.mozilla.org\/en-US\/firefox\/addon\/poster\/<\/a><\/p>\n<p>Ty\u00f6kalu k\u00e4ynnistyy Firefoxin Tools-valikosta.<\/p>\n<p><strong>REST-palvelun toteutus Node.js:ll\u00e4<\/strong><\/p>\n<p>Toteutamme seuraavaksi yksinkertaisen REST-palvelun joka vastaa POST, GET ja DELETE\u00a0pyynt\u00f6ihin, tallentaen ja hakien dataa JSON-muodossa. GET ilman parametreja palauttaa kaikki tietoalkiot tai jos parametrina annetaaan id, palautetaan alkio\u00a0kyseisell\u00e4 id:ll\u00e4. POST generoi alkiolle uuden id:n, tallentaa alkion palvelun sis\u00e4iseen taulukkoon ja lopuksi palauttaa alkion id:ll\u00e4 varustettuna takaisin kutsujalle. DELETE poistaa tiedot annetulla id:ll\u00e4.<\/p>\n<p>Palvelun toteutus olettaa ett\u00e4 Node.js:lle on ladattu\u00a0expess ja body-parser\u00a0kirjastot.<\/p>\n<pre title=\"simple-rest-service.js\" class=\"lang:js decode:true  \">var express = require('express');   \/\/ for easy HTTP server\r\nvar application = express();\r\n\r\nvar bodyParser = require('body-parser');\r\napplication.use(bodyParser.urlencoded({\r\n\u00a0\u00a0\u00a0 extended: true\r\n}));\r\napplication.use(bodyParser.json());\r\n\r\n\/\/ this is needed to allow connection from any address:\r\napplication.use(function(req, res, next) {\r\n  res.header(\"Access-Control-Allow-Origin\", \"*\");\r\n  res.header(\"Access-Control-Allow-Headers\", \"Origin, X-Requested-With, Content-Type, Accept\");\r\n  res.header(\"Access-Control-Allow-Methods\", \"GET,POST,DELETE\"); \/\/ PUT is not implemented\r\n  next();\r\n});\r\n\r\n\/\/ array to store items\r\nvar items = [];\r\n\r\n\/\/ POST\r\napplication.post('\/items\/', function (req, res) {\r\n   console.log('POST received'); \r\n   console.log(req.body);\r\n   var item = req.body;\r\n   var id = generateGuid();\r\n   item.id  = id;\r\n   console.log(id);\r\n   items.push(item);\r\n   var responseItem = JSON.stringify(item);\r\n   res.end(responseItem);\r\n});\r\n\r\n\/\/ This is one way to generate new id\r\nfunction generateGuid() {\r\n    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(\/[xy]\/g, function(c) {\r\n        var r = Math.random()*16|0, v = c == 'x' ? r : (r&amp;0x3|0x8);\r\n        return v.toString(16);\r\n    });\r\n}\r\n\r\n\/\/ GET: get all items\r\napplication.get('\/items\/', function (req, res) {\r\n    console.log('GET all received'); \r\n   var responseItems = JSON.stringify(items);\r\n   res.end(responseItems);\r\n});\r\n\r\n\/\/ GET: get item(s) with id\r\napplication.get('\/items\/:id', function (req, res) {\r\n    console.log('GET with id received'); \r\n    var filtered = items.filter(x =&gt; x.id==req.params.id);\r\n    var responseJSON = JSON.stringify(filtered);\r\n    res.end(responseJSON);\r\n});\r\n\r\n\/\/ DELETE: delete item(s) ith id\r\napplication.delete('\/items\/:id', function(req, res) {\r\n    console.log('DELETE with id received');   \r\n    items = items.filter(i=&gt;i.id!=req.params.id);\r\n    res.send({success : true});\r\n});\r\n\r\n\/\/ Start server\r\nvar server = application.listen(8080, function () {\r\n  var port = server.address().port;\r\n  console.log('Simple REST API listening on port %s', port);\r\n});<\/pre>\n<p>Seuraavaksi k\u00e4ynnistet\u00e4\u00e4n yll\u00e4 toteutettu palvelu komentorivilt\u00e4:<\/p>\n<p><a href=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_start.jpg\" rel=\"attachment wp-att-240\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-240 size-full\" src=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_start.jpg\" alt=\"srs_start\" width=\"596\" height=\"284\" srcset=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_start.jpg 596w, https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_start-300x143.jpg 300w\" sizes=\"auto, (max-width: 596px) 100vw, 596px\" \/><\/a><\/p>\n<p>Sitten k\u00e4ynnistet\u00e4\u00e4n testausty\u00f6kalu eli POSTER lis\u00e4osa selaimesta.<\/p>\n<p>Ensimm\u00e4inen palvelupyynt\u00f6 on uuden tiedon tallennus POST metodilla jonka vastauksena saadaan 200 OK ja tallennettu tieto id:ll\u00e4 varustettuna:<\/p>\n<p><a href=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_post.jpg\" rel=\"attachment wp-att-241\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-241\" src=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_post.jpg\" alt=\"srs_post\" width=\"640\" height=\"525\" srcset=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_post.jpg 895w, https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_post-300x246.jpg 300w, https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_post-768x630.jpg 768w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p>Tallennetaan saman tien toinen tieto:<\/p>\n<p><a href=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_post2.jpg\" rel=\"attachment wp-att-243\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-243\" src=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_post2.jpg\" alt=\"srs_post2\" width=\"640\" height=\"546\" srcset=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_post2.jpg 868w, https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_post2-300x256.jpg 300w, https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_post2-768x656.jpg 768w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p>Sitten haetaan tiedot GET pyynn\u00f6ll\u00e4 ja vastauksena saadaan kaksi tietoalkiota:<\/p>\n<p><a href=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_get.jpg\" rel=\"attachment wp-att-242\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-242\" src=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_get.jpg\" alt=\"srs_get\" width=\"650\" height=\"464\" srcset=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_get.jpg 816w, https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_get-300x214.jpg 300w, https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_get-768x548.jpg 768w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/a><\/p>\n<p>Kokeillaan poistaa toinen tietoalkio DELETE pyynn\u00f6ll\u00e4 (huomaa id parametrina urlissa):<\/p>\n<p><a href=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_delete.jpg\" rel=\"attachment wp-att-244\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-244\" src=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_delete.jpg\" alt=\"srs_delete\" width=\"640\" height=\"532\" srcset=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_delete.jpg 897w, https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_delete-300x249.jpg 300w, https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_delete-768x639.jpg 768w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p>Kun nyt tehd\u00e4\u00e4n viel\u00e4 yksi GET pyynt\u00f6, n\u00e4hd\u00e4\u00e4n ett\u00e4 toinen tietoalkio on poistunut palvelimelta:<\/p>\n<p><a href=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_get2.jpg\" rel=\"attachment wp-att-245\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-245\" src=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_get2.jpg\" alt=\"srs_get2\" width=\"640\" height=\"576\" srcset=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_get2.jpg 818w, https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_get2-300x270.jpg 300w, https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2016\/06\/srs_get2-768x691.jpg 768w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p>Yhteenvetona voidaan todeta ett\u00e4 Node.js:ll\u00e4 on todella helppo pystytt\u00e4\u00e4 yksinkertainen REST-palvelu joka k\u00e4ytt\u00e4\u00e4 JSON formaattia tiedon v\u00e4litt\u00e4miseen.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Yleist\u00e4 RESTist\u00e4 REST-palvelu on yleinen tapa toteuttaa tietopalvelun rajapinta web-palvelulle. REST-palvelu on ulosp\u00e4in itse asiassa kuin &#8221;perinteinen&#8221; HTTP-palvelu ja REST-rajapinta vastaa samoihin pyynt\u00f6ihin kuin perus HTTP-palvelin. My\u00f6s HTTP -statuskoodit ovat k\u00e4yt\u00f6ss\u00e4 eli onnistunut REST-palvelupyynn\u00f6n k\u00e4sittely palauttaa statuskoodin 200 OK, ep\u00e4onnistunut tiedonhaku (vaikkapa haku\u00a0id:ll\u00e4 jota ei l\u00f6ydy tietokannasta) palauttaa statuskoodin 404\u00a0 Not found, jne. Erona perus &#8230; <a title=\"REST palvelun pystytys\" class=\"read-more\" href=\"https:\/\/www.pilvikoodari.net\/?p=218\" aria-label=\"Lue lis\u00e4\u00e4 aiheesta REST palvelun pystytys\">Lue lis\u00e4\u00e4<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10,6],"tags":[],"class_list":["post-218","post","type-post","status-publish","format-standard","hentry","category-json","category-node-js"],"_links":{"self":[{"href":"https:\/\/www.pilvikoodari.net\/index.php?rest_route=\/wp\/v2\/posts\/218","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pilvikoodari.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pilvikoodari.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pilvikoodari.net\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pilvikoodari.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=218"}],"version-history":[{"count":26,"href":"https:\/\/www.pilvikoodari.net\/index.php?rest_route=\/wp\/v2\/posts\/218\/revisions"}],"predecessor-version":[{"id":418,"href":"https:\/\/www.pilvikoodari.net\/index.php?rest_route=\/wp\/v2\/posts\/218\/revisions\/418"}],"wp:attachment":[{"href":"https:\/\/www.pilvikoodari.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=218"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pilvikoodari.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=218"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pilvikoodari.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=218"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}