4. diel - Kompletné Restful API v Node.js
V minulej lekcii, Rozbehnutie projektu a prvé riadky v Expressu , sme si pripravili pracovné prostredie a začali sme používať knižnicu Express. Dnes v tutoriálu implementujeme kompletný Restful API v Node.js pre databázu filmov. Cestou sa naučíme používať niekoľko užitočných nástrojov.
Založenie projektu
Minule sme si pomocou NPM založili projekt a nainštalovali express. Pre dnešný aplikácii si vytvoríme nový projekt. Pre istotu si ešte raz uveďme príslušné príkazy:
mkdir node-projekt cd node-projekt npm init --yes npm install express
V projekte potom ako minule do nového súboru index.js
napíšeme nasledujúci kód:
const express = require('express'); const app = express(); app.listen(3000, () => console.log('Listening on port 3000...'));
Nodemon
Ak ste minule počas čítania článku písali aj kód, mohlo vás
otravovať, že pri každej úprave kódu bolo treba aplikáciu reštartovať.
Nástroj nodemon ponúka lepšie riešenie. Nodemon je skratka za node
monitor. Stráži všetky súbory typu .js
(a pár ďalších
typov) v danej zložke a podpriečinkoch. Kedykoľvek sa niektorý z týchto
súborov zmení, nodemon aplikáciu sám reštartuje. Všetky zmeny tak môžeme
rovno vyskúšať.
Nodemon nainštalujeme opäť pomocou NPM. Väčšinou ho chceme
nainštalovať globálne, s použitím parametra -g
. Potom už len
stačí zadať do príkazového riadku namiesto príkazu
node index.js
príkaz nodemon index.js
:
npm install -g nodemon nodemon index.js
Metóda GET
Metódu GET sme používali už minule. Novo bude vracať všetky filmy alebo detail jedného konkrétneho filmu. K tomu budeme samozrejme najskôr potrebovať databázu filmov.
Príprava dát
Pre začiatok nebudeme ešte používať databázu (tú si pridáme v niektorej z najbližších lekcií), ale budeme filmy držať v poli.
const movies = [ { id: 1, name: "Kill Bill", year: 2003 }, { id: 2, name: "Kill Bill 2", year: 2004 }, { id: 3, name: "Star Wars IV", year: 1976 }, { id: 4, name: "Star Wars V", year: 1980 } ];
O filmoch by sme mohli uchovávať oveľa viac dát (a v databáze tiež budeme), zatiaľ nám však postačí id, meno filmu a rok premiéry.
Implementácia metódy GET pre vás nebude ťažké, ak ste dobre čítali predchádzajúce lekciu. Prehľad ciest sme si urobili už v druhej lekcii a metódu GET už vieme:
app.get('/api/movies', (req, res) => { res.send(movies); }); app.get('/api/movies/:id', (req, res) => { const id = Number(req.params.id); const movie = movies.find( movie => movie.id === id); if (movie) { res.send(movie); } else { res.status(404).send('Film nebyl nalezen.'); } });
V prvom volanie metódy app.get()
bez parametra sa pýtame na
všetky filmy, vráti sa teda celé pole. Pri druhom volaní požívame
parameter id
, pomocou metódy find()
na vyhľadávanie
v poli nájdeme správny film a vrátime ho. Ak by film neexistoval, vrátime
chybovú hlášku a HTTP kód 404 Not Found
(požadovaný
dokument nebol nájdený).
Teraz už aplikáciu nemusíte reštartovať, stačí kód uložiť. Po
zadaní http://localhost:3000/api/movies
do adresného riadku sa
zobrazí zoznam filmov:
Alebo môžete pridať ešte jedno lomítko a id filmu, zobrazí sa len dáta o konkrétnom filme.
Skúste si zadať aj id, pre ktoré film neexistuje, zobrazí sa chybová hláška (a vo vývojárskych nástrojoch pod klávesom F12 sa v paneli "Network" môžete presvedčiť, že vám server vrátil kód 404).
Metóda POST
Určite ste si všimli, že sa pole s filmami v prehliadači nezobrazilo veľmi pekne. Prehliadač je totiž určený pre vykresľovanie webových stránok, nie pre zobrazovanie polí. Požiadavka s metódou POST by sme dokonca mali problém aj odoslať.
Postman
Preto sa hodí mať aplikáciu, ktorá nám umožní posielať všetky typy požiadaviek. Jednou takou je Postman. Stiahnite si ho z www.getpostman.com. Inštaláciu určite zvládnete sami.
Po spustení zvolíme metódu GET (1), do adresného riadku napíšeme to isté čo do adresného riadku prehliadača (2), a klikneme na tlačidlo "Send" (3).
Zobrazí sa nám zoznam filmov alebo konkrétny film, podľa toho, s akou
cestou sme požiadavku poslali. Okrem toho nám Postman ukazuje HTTP kód
200 OK
, s ktorým odpoveď prišla (4) a mnoho ďalších
informácií.
Môžete si ešte vyskúšať, že vráti kód 404 pri zadaní GET požiadavke na neexistujúce id filmu. Rovnako ako v prehliadači si v ňom môžete vytvárať záložky na rôzne požiadavky pomocou tlačidla + (5).
Od teraz už budeme všetky požiadavky na naše API posielať pomocou Postman.
Implementácia POST
Keď máme Postman, môžeme si naimplementovať metódu POST. Do
index.js
vložme nasledujúci kód (a súbor uložme):
app.post('/api/movies', (req, res) => { const movie = { id: movies.length + 1, name: req.body.name, year: req.body.year }; movies.push(movie); res.send(movie); });
Teraz voláme metódu app.post()
. Požiadavka posielame na cestu
bez parametra, pretože id nový film ešte nemá priradený. Teraz ho tvoríme
ako dĺžku poľa plus jedna. (To nemusí byť vždy správne, ale vzhľadom k
tomu, že časom to za nás bude robiť databázy, tak nám to tentokrát bude
stačiť.) Potom už len pridáme film do databázy a tiež ho zobrazíme ako
odpoveď (v odpovedi sa zobrazí vrátane novo vytvoreného id).
Aby kód fungoval, musíme na začiatok súboru (hneď po tom, čo definujeme
konštantu app
) pridať ešte tento riadok:
app.use(express.json());
Tým voláme takzvané middleware, čo sú procesy, ktoré sa
spúšťa medzi prijatím požiadavky a odoslaním odpovede (sú
uprostred, preto middleware). Konkrétne
express.json()
dekóduje telo požiadavke, a pokiaľ v ňom nájde
nejaký JSON, tak s ním naplní hodnotu vlastnosti req.body
. Bez
tohto middleware by sme v req.body
nič nenašli.
Teraz už môžeme prejsť do Postman a na novej záložke (1) založiť novú požiadavku. Metóda bude POST (2), vyplníme adresu, nastavíme telo požiadavke (3), vyberieme raw (4) a typ JSON (5).
Do tela požiadavke vyplníme šiesty diel Star Wars, ktorý nám v pôvodnom zozname chýbal. Nezabudnite, že všetko musí byť presne podľa formátu JSON, teda aj mená vlastností musí byť v úvodzovkách. A môžeme požiadavku poslať kliknutím na tlačidlo "Send".
Validácia
Je to trochu odbočka, ale je to tak dôležité, že to nemožno nespomenúť:
Vždy overujte, či dáta, ktorá vám niekto posiela, sú v poriadku a zodpovedajú tomu, čo očakávate.
Zatiaľ si posielate do svojej aplikácie dáta sami, z Postman, takže si nebudete úmyselne posielať zlé dáta. Ale ste si istí, že tam nemáte žiadny preklep? A čo keď bude dáta posielať niekto cudzí?
Rýchlu validáciu si môžete napísať sami - stačilo by overiť, že meno filmu je reťazec a rok premiéry je číslo. Ale opäť - časom budeme potrebovať komplexnejšie validáciu, a prečo písať veľa kódu navyše, keď na ňu už existujú hotové balíky? Jeden z nich, veľmi obľúbený, sa volá Joi.
Nainštalujeme si ho pomocou NPM:
npm install joi
Na začiatok index.js
pridajme nasledujúci kód:
const Joi = require('joi');
To, čo sa nám vracia pri použití require()
, je trieda, preto
veľké J
.
Na koniec súboru pridajme funkciu validateMovie()
:
function validateMovie(movie) { const schema = { name: Joi.string().min(3).required(), year: Joi.number() }; return Joi.validate(movie, schema); }
Vo funkcii validateMovie()
definujeme schému, ktoré hovorí,
že meno bude reťazec o minimálnej dĺžke troch znakov a je povinné. Rok
musí byť číslo a povinný nie je. Potom pomocou metódy
Joi.validate()
porovnáme JSON z tela požiadavke (parameter
movie
) s uvedeným schémou.
Metódu app.post()
potom môžeme upraviť napríklad takto:
app.post('/api/movies', (req, res) => { const { error } = validateMovie(req.body); if (error) { res.status(400).send(error.details[0].message); } else { const movie = { id: movies.length + 1, name: req.body.name, year: req.body.year }; movies.push(movie); res.send(movie); } });
Ak požiadavka nezodpovedá schéme, vracia sa nám objekt s vlastnosťou
error
. V tomto prípade vrátime užívateľovi chybovú hlášku,
ktorú nám pripravil Joi
, spolu s HTTP kódom
400 Bad Request
. Ak je všetko v poriadku, vlastnosť
error
v objekte neexistuje a zvyšný kód prebehne rovnako ako
predtým.
Skúste si teraz poslať z Postman niekoľko POST požiadaviek s validnými alebo so zlými dátami a sledujte správanie aplikácie.
Metóda PUT
Ak ste filmoví znalci, iste vám neuniklo, že máme v kóde zlý rok u štvrtého dielu Star Wars. Poďme ho teda opraviť - naučíme naše API obsluhovať metódu PUT.
Do index.js
vložme nasledujúci kód (a súbor nezabudnime
uložiť):
app.put('/api/movies/:id', (req, res) => { const id = Number(req.params.id); const movie = movies.find(movie => movie.id === id); if (!movie) { res.status(404).send('Film nebyl nalezen.'); return; } const { error } = validateMovie(req.body); if (error) { res.status(400).send(error.details[0].message); } else { movie.name = req.body.name; movie.year = req.body.year; res.send(movie); } });
Opakujú sa tu veci, čo sme už použili v iných metódach, takže nie je
potrebné kód znova vysvetľovať. Prejdeme opäť do Postman, na novej
záložke vyberieme metódu PUT, pošleme ju na koncový bod
http://localhost:3000/api/movies/3
a do tela vložíme nasledujúce
JSON:
{ "name": "Star Wars IV", "year": 1977 }
Nezabudnite vybrať raw a typ JSON. A potom len overte, pomocou GET požiadavke, že filmy už majú správne nastavený rok premiéry.
Metóda DELETE
A zostáva nám metóda DELETE. To už teraz bude jednoduché:
app.delete('/api/movies/:id', (req, res) => { const id = Number(req.params.id); const movie = movies.find(movie => movie.id === id); if (!movie) { res.status(404).send('Film nebyl nalezen.'); } else { const index = movies.indexOf(movie); movies.splice(index, 1); res.send(movie); } });
Kódu už určite rozumiete. Nezabudnite si pomocou Postman poslať DELETE požiadavku, aby ste otestovali, že to naozaj funguje.
Nabudúce, v lekcii Úvod do MongoDB , si povieme niečo o databázach a hlavne o MongoDB.
Opäť poznámka na záver: ES6 object destructuring
Ak ste si nevedeli rady s premennou error
deklarovanou v
zložených zátvorkách, jedná sa tzv. Object destructuring. Miesto
vysvetľovanie vám radšej ukážem krátky kód:
const obj = { a: 1, b: 2, c: 3 }; const { a, b } = obj;
V konštantách a
a b
budú uložené údaje,
ktoré sa prečítajú zvnútra objektu. Teda v a
bude po
prebehnutí kódu uložená jednotka a v b
dvojka.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 376x (3.39 kB)
Aplikácia je vrátane zdrojových kódov v jazyku JavaScript