Harjutus 1:
REST API – REST on mittekohustuslikke soovitusi (best practices), kuidas hästikäituvad rakendused võiksid andmeid üle veebi (see tähendab kasutades HTTP protokolli) vahetada ja igal veebiteenuse ehitajal on RESTist oma spetsiifiline nägemus
REST-i (Representational State Transfer) on tavaliselt nimetatud pigem veebiteenuste arhitektuuristiiliks kui protokolliks või standardiks.
Harjutus osa:
1. Paigalda Node.js
2. Loo töölauale kaust rest–api
3. Käivita koodiredaktor (nt VS Code, WebStorm vms) ja ava see kaust projektina
4. Loo kausta fail index.js järgneva sisuga:
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors()); // Avoid CORS errors in browsers
app.use(express.json()) // Populate req.body
const widgets = [
{ id: 1, name: "Cizzbor", price: 29.99 },
{ id: 2, name: "Woowo", price: 26.99 },
{ id: 3, name: "Crazlinger", price: 59.99 },
]
app.get('/widgets', (req, res) => {
res.send(widgets)
})
app.get('/widgets/:id', (req, res) => {
if (typeof widgets[req.params.id - 1] === 'undefined') {
return res.status(404).send({ error: "Widget not found" })
}
res.send(widgets[req.params.id - 1])
})
app.post('/widgets', (req, res) => {
if (!req.body.name || !req.body.price) {
return res.status(400).send({ error: 'One or all params are missing' })
}
let newWidget = {
id: widgets.length + 1,
price: req.body.price,
name: req.body.name
}
widgets.push(newWidget)
res.status(201).location('localhost:8080/widgets/' + (widgets.length - 1)).send(
newWidget
)
})
app.listen(8080, () => {
console.log(`API up at: http://localhost:8080`)
})

5. Käivita koodiredaktoris terminal ja seal järgnevad käsud:
1. npm init -y // package.json initsialiseerib node projekti
2. npm i express cors // kausta node_moodules installib express ja cors paketti
3. node . //käivitab index.js faili
npm init -y
npm i express cors
node .
6. Tee terminalis xh
’ga GET päring vastu API-t:

xh -v localhost:8080/widgets
7. Tee terminalis xh’ga GET päring vastu API-t, mis tagastab kõik vidinad

xh -v localhost:8080/widgets/1
8. Tee terminalis xh’ga POST päring vastu API-t, mis lisab uue vidina:

xh -v localhost:8080/widgets name=Fozzockle price=39.99
9. Tee terminalis xh’ga POST päring vastu API-t, mis kustutab ühe vidina:

xh -v DELETE localhost:8080/widgets/2
Harjutus 2: Loo Codesandbox-is HTML leht, mis kuvab auto andmeid
Kasutades juhiseid lisasin vajalikud andmed ja tegin selle kuvamiseks, kõik see tegin Sandboxi saidil
Kopeerisin ülesande koodi ja lisasin seejärel vajalikud read ja andmed.
import "./styles.css";
const myjson = [
{
"Car 0": {
Color: "Rose Red",
"Tinted Windows": false,
Wheels: 4,
"Roof Cargo": null,
Audiosystem: "FM Radio, MP3, MP4 and MKV player, harman/kardon speakers",
Accessories: "satnav, cruise control",
},
Car1: {
Color: "Navy blue",
"Tinted Windows": true,
Wheels: 4,
"Roof Cargo": "Thule",
Audiosystem:
"FM Radio, Apple CarPlay/Android Auto, Bowers & Wilkins Premium Sound speakers",
Accessories: "self drive system, luggage cover",
},
},
];
document.getElementById("app").innerHTML = `
<div id="json">
<h1> Car Properties </h1>
<h2> Car 0 </h2>
<p>Color: ${myjson[0]["Car 0"].Color}</p>
<p>Tinted Windows: ${myjson[0]["Car 0"]["Tinted Windows"]}</p>
<p>Wheels: ${myjson[0]["Car 0"].Wheels}</p>
<p>Roof Cargo: ${myjson[0]["Car 0"]["Roof Carho"]}</p>
<p>Audiosystem: ${myjson[0]["Car 0"].Audiosystem}</p>
<p>Accessories: ${myjson[0]["Car 0"].Accessories}</p>
<h2> Car1 </h2>
<p>Color: ${myjson[0].Car1.Color}</p>
<p>Tinted Windows: ${myjson[0].Car1["Tinted Windows"]}</p>
<p>Wheels: ${myjson[0].Car1.Wheels}</p>
<p>Roof Cargo: ${myjson[0].Car1["Roof Carho"]}</p>
<p>Audiosystem: ${myjson[0].Car1.Audiosystem}</p>
<p>Accessories: ${myjson[0].Car1.Accessories}</p>
</div>
`;
Võtsin jooned ja andmed allolevalt pildilt:


Lõppkokkuvõttes näeb see välja nii:

Harjutus 3: sessionStorage
Ava konsool ning kirjuta konsoolile sessionStorage
ning vajuta ENTER. Näed, et Session Storage on tühi.
Tee uus käsk sessionStorage.setItem('color','orange')
. Selle käsuga lisati Session Storage’isse uued andmed.
Kirjuta uus käsk sessionStorage.getItem('color')
ning näed, et väljastatakse sessionStorage’ist sinu lemmikvärv.

Et näha, mis on Session Storage’isse salvestatud, mine Application>Session Storage>vastav domeen

Harjutus 4: localStorage
Mine sellele vahekaardile tagasi, kus viimati sessionStorage käske sooritasid.
Ava uuesti konsool ning kirjuta localStorage
. Näed, et see on tühi.
Tee uus käsk localStorage.setItem('car','skoda')
. Selle käsuga lisati Local Storage’isse uued andmed.
Soorita käsk localStorage.getItem(car) ning näed, et localStoragesse väljastatakse sinu lemmikauto.

Nüüd tee uuesti uus vaheaken ning vaata Application>Local Storage alla. Näed, et see on sinna salvestatud.

Harjutus 5: Küpsised
xh on HTTP-klient, millel on sõbralik käsurea liides. See püüab saada loetavat väljundit ja hõlpsasti kasutatavaid valikuid. xh ühildub enamasti HTTPie-ga: vt http(1). Suvandit –curl saab päringu saatmise asemel kasutada käsu curl(1) tõlke printimiseks.


Harjutus 6: Peekon API
Ava veebilehitsejas Code Sandbox sait
Vali Official Templates alt static
Kirjuta pildil olev kood index.html faili. Alustuseks kasuta HTML trafaretti (hüüumärk ja tab klahv).
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Styled Template</title>
</head>
<body>
<button type="button" onclick="loadDoc()">Request bacon</button>
<p id="demo"></p>
<script>
function loadDoc() {
const xhttp = new XMLHttpRequest();
xhttp.onload = function () {
const response = JSON.parse(this.responseText);
const listContainer = document.getElementById("demo");
const ul = document.createElement("ul");
response.forEach(function (item) {
const li = document.createElement("li");
li.textContent = item;
ul.appendChild(li);
});
listContainer.innerHTML = "";
listContainer.appendChild(ul);
};
xhttp.open("GET", "https://baconipsum.com/api/?type=all-meat");
xhttp.send();
}
</script>
</body>
</html>
styles.css:
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
color: #333;
text-align: center;
margin-top: 50px;
}
button {
background-color: #ff6347;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
transition: background-color 0.3s ease;
}
button:hover {
background-color: #ff4500;
}
p {
margin-top: 20px;
font-size: 18px;
}
Sandbox:
https://codesandbox.io/p/sandbox/zwt8c3

Harjutus 7: Github API
Selle ülesande puhul peate looma veebirakenduse, mis kasutab kasutajaprofiili andmete toomiseks GitHubi avalikku API-d.
- REST (Representational State Transfer) on arhitektuurimudel, mida kasutatakse veebiteenuste loomisel ja rakenduste vahelise suhtluse lihtsustamiseks
- Github access token – Kasutaja juurdepääsuluba on teatud tüüpi OAuthi luba. Erinevalt traditsioonilisest OAuthi märgist ei kasuta kasutaja juurdepääsuluba ulatust. Selle asemel kasutab see peeneteralisi õigusi.
- FETCH – on JavaScripti sisseehitatud funktsioon, mis on loodud HTTP-päringute tegemiseks. See võimaldab teil kaugserverist andmeid vastu võtta ja vastuseid töödelda.
import "./styles.css"; // Impordi stiilid välisest failist
// Muutujad profiiliandmete salvestamiseks
let profileName = "";
let profileId = "";
let profileLink = "";
let profileRepos = "";
let profilePicture = "";
// Asünkroonne funktsioon GitHubi profiiliandmete pärimiseks
async function fetchProfile(username) {
try {
// Tee päring GitHubi API-le profiiliandmete saamiseks
const response = await fetch(`https://api.github.com/users/${username}`);
// Muuda vastus JSON formaati
const data = await response.json();
// Uuenda muutujaid saadud andmetega
profileName = data.login;
profileId = data.id;
profileLink = data.html_url;
profileRepos = data.public_repos;
profilePicture = data.avatar_url;
// Kuvage uuendatud andmed lehel
renderPage();
} catch (error) {
// Käsitle päringu vigu
console.error("Viga profiili pärimisel:", error);
}
}
// Funktsioon lehe sisu kuvamiseks
function renderPage() {
// Uuenda elemendi sisu, mille id on "app"
document.getElementById("app").innerHTML = `
<div>
<h1>Github profiili vaatamine</h1>
<p>Palun sisesta profiilinimi: </p>
<input id="username-input" /> <!-- Sisendväli kasutajanime sisestamiseks -->
<div class="content">
<h1 id="name">Nimi: ${profileName}</h1>
<p id="id">Id: ${profileId}</p>
<p id="reports">Avalikud repod: ${profileRepos}</p>
<p id="profile-url">
Link: <a href="${profileLink}" target="_blank">/users/${profileName}</a>
<!-- Link kasutaja profiilile -->
</p>
<div id="profile-avatar">
<img src="${profilePicture}" alt="${profileName} profiilifoto laadimine...."
style="width: 100px; height: 100px; border-radius: 60%;" />
<!-- Kasutaja avatar -->
</div>
</div>
</div>
`;
// Lisa sündmuste töötleja sisendväljale
document
.getElementById("username-input")
.addEventListener("keyup", function (event) {
// Kontrolli, kas vajutati Enteri klahvi
if (event.key === "Enter") {
// Hangi kasutaja nimi sisendväljalt
const username = event.target.value;
// Kutsu välja profiili pärimise funktsioon
fetchProfile(username);
}
});
}
// Esmane lehe kuvamine
renderPage();
body {
background: linear-gradient(135deg, #000, #1a1a1a), url("clonnex.gif");
background-size: cover;
background-blend-mode: overlay;
color: #e0e0e0;
font-family: "Roboto", sans-serif;
margin: 0;
padding: 20px;
}
h1 {
color: #ff3399;
font-size: 36px;
font-weight: 700;
text-shadow: 2px 2px 5px rgba(255, 51, 102, 0.6);
margin-bottom: 15px;
letter-spacing: 1.5px;
}
p {
font-size: 20px;
line-height: 1.8;
margin: 0;
}
#json {
background: rgba(28, 28, 28, 0.9);
border-radius: 12px;
padding: 25px;
margin-bottom: 25px;
box-shadow: 0 6px 12px rgba(255, 0, 102, 0.4);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
#json:hover {
transform: translateY(-5px);
box-shadow: 0 8px 16px rgba(255, 0, 102, 0.6);
}
#json:last-child {
margin-bottom: 0;
}
Harjutus 8: XML Kuvamine Lehel
XML (Extensible Markup Language) on W3C poolt välja töötatud ja soovitatud standardne üldotstarbeline märgistuskeel struktureeritud teabe vahetamiseks infosüsteemide vahel, eriti veebirakendustes Internetis.
XML kuvamine läbi JS
games.xml:
<?xml version="1.0" encoding="UTF-8"?>
<gameslist>
<game>
<title lang="en">Hearthstone</title>
<price>Free</price>
<platforms>
<platform>PC</platform>
<platform>Mobile</platform>
</platforms>
</game>
<game>
<title lang="en">Dota2</title>
<price>Free</price>
<platforms>
<platform>PC</platform>
</platforms>
</game>
<game>
<title lang="en">TESV</title>
<price>30</price>
<platforms>
<platform>PC</platform>
<platform>PS4</platform>
<platform>XBOX</platform>
</platforms>
</game>
</gameslist>
index.js:
document.getElementById("app").innerHTML = "<table id='xmlTable'></table>";
let xmlhttp = new XMLHttpRequest(); // Create an XMLHttpRequest object
xmlhttp.open("GET", "src/games.xml", false);
xmlhttp.send();
let XMLContent = xmlhttp.responseXML;
let tableRows =
"<thead><tr><th>Title</th><th>Price</th><th>Platform</th></tr></thead>";
let gameElements = XMLContent.getElementsByTagName("game");
for (let i = 0; i < gameElements.length; i++) {
tableRows +=
"<tr><td>" +
gameElements[i].getElementsByTagName("title")[0].childNodes[0].nodeValue +
"</td><td>" +
gameElements[i].getElementsByTagName("price")[0].childNodes[0].nodeValue +
"</td><td>";
let platforms = gameElements[i].getElementsByTagName("platform");
for (let j = 0; j < platforms.length; j++) {
tableRows += platforms[j].childNodes[0].nodeValue + "/";
}
tableRows += "</td></tr>";
}
document.getElementById("xmlTable").innerHTML = tableRows;
styles.css:
#xmlTable {
border-collapse: collapse;
width: 100%;
margin-top: 20px;
}
#xmlTable th,
#xmlTable td {
border: 1px solid gray;
padding: 8px;
text-align: left;
}
#xmlTable th {
background-color: gray;
}
#xmlTable tr:nth-child(even) {
background-color: #f9f9f9;
}
#xmlTable tr:hover {
background-color: #ddd;
}
#xmlTable th {
cursor: pointer;
}

Harjutus 10: Saada Email Github Push-l
Kui esitate muudatusi GitHubi repositooriumi, on hea mõte luua informatiivne kommiteerimisteade. Ja see ülesanne võimaldab meil mõista, kuidas saata push-in e-kirju Githubile.


Kopeeritud tühi kaustas loome -> .github , .github kaustas loome -> workflows ja seal loome pildil olev fail, sisuga.
name: Send email on push
on:
push:
branches:
- main # Kontrollib, kas push on tehtud 'main' harusse
jobs:
mail_on_push:
runs-on: ubuntu-latest
steps:
- name: Send mail
# kasutatakse GitHubi tegevust e-kirjade saatmiseks
uses: dawidd6/action-send-mail@v3
with:
# SMTP serveri aadress ja port Gmaili jaoks
server_address: smtp.gmail.com
server_port: 465
# kasutajanimi ja parool, mis on salvestatud GitHubi saladustesse
username: ${{ secrets.MAIL_USERNAME }}
password: ${{ secrets.MAIL_PASSWORD }}
subject: "Push Notification for ${{ github.repository }} on branch ${{ github.ref }}"
to: "arkadikorotitsh@gmail.com"
body: |
Tehti push järgmisele repositooriumile: ${{ github.repository }} harusse: ${{ github.ref }}.
**Detailid:**
- Commit: ${{ github.sha }}
- Commiti sõnum: ${{ github.event.head_commit.message }}
- Commiti autor: ${{ github.event.head_commit.author.name }} ({{ github.event.head_commit.author.email }})
- Pusher: ${{ github.event.pusher.name }}
- **Pushi kuupäev ja aeg**: ${{ github.event.head_commit.timestamp }}
Vaata commit'i GitHubis: [Commiti link](${{ github.event.head_commit.url }})
# saatja nimi, mis kuvatakse e-kirjas
from: Github Actions
saadetud sõnum on kättesaadetud

Harjutus 11: Websocket API
WebSocket API võimaldab kliendil luua kahepoolset („dupleks“) suhtlust serveriga.
server:

client:

index.html
<!doctype html>
<form name="publish">
<input type="text" name="message" maxlength="50"/>
<input type="submit" value="Send"/>
</form>
<div id="messages"></div>
<script>
let url = location.host == 'localhost' ?
'ws://localhost:8080/ws' : location.host == 'javascript.local' ?
`ws://javascript.local/article/websocket/chat/ws` : // dev integration with local site
`wss://javascript.info/article/websocket/chat/ws`; // prod integration with javascript.info
//loome objekti koos veebisoketiga
let socket = new WebSocket(url);
// sõnumi saatmine vormile
document.forms.publish.onsubmit = function() {
let outgoingMessage = this.message.value;
socket.send(outgoingMessage);
return false;
};
// töödelda sissetulevaid sõnumeid
socket.onmessage = function(event) {
let incomingMessage = event.data;
showMessage(incomingMessage);
};
//kui kasutaja on socket'i sulgenud, kirjutame sellest konsooli.
socket.onclose = event => console.log(`Closed ${event.code}`);
// Näita sõnumeid div#messages
function showMessage(message) {
let messageElem = document.createElement('div');
messageElem.textContent = message;
document.getElementById('messages').prepend(messageElem);}
</script>
index.js
//Node’i WebSocket’i sisaldamine.
const http = require('http');
const fs = require('fs');
const ws = require('ws');
//Serveri seadistamine
const wss = new ws.Server({ noServer: true });
function accept(req, res) {
if (req.url === '/ws' && req.headers.upgrade &&
req.headers.upgrade.toLowerCase() === 'websocket' &&
req.headers.connection.match(/\bupgrade\b/i)) {
wss.handleUpgrade(req, req.socket, Buffer.alloc(0), onSocketConnect);
} else if (req.url === '/') {
// Отправляем index.html
fs.createReadStream('./index.html').pipe(res);
} else {
// Страница не найдена
res.writeHead(404);
res.end();
}
}
//Ühenduse loomine
const clients = new Set();
function onSocketConnect(ws) {
clients.add(ws);
ws.on('message', function(message) {
message = message.slice(0, 50); // максимальная длина сообщения — 50 символов
for (let client of clients) {
client.send(message);
}
});
ws.on('close', function() {
log('connection closed');
clients.delete(ws);
});
}
//Teksti kuvamine
let log;
if (!module["parent"]) {
log = console.log;
http.createServer(accept).listen(8080);
} else {
log = function() {};
// log = console.log;
exports.accept = accept;
}
style.css
body {
font-family: Arial, sans-serif;
background-color: #f9f9f9;
margin: 0;
padding: 20px;
}
form {
margin-bottom: 20px;
}
input[type="text"] {
width: 70%;
padding: 8px;
font-size: 14px;
border: 1px solid #ccc;
border-radius: 4px;
}
input[type="submit"] {
padding: 8px 16px;
font-size: 14px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
input[type="submit"]:hover {
background-color: #45a049;
}
#messages {
margin-top: 20px;
}
#messages div {
background-color: #e1f5fe;
padding: 10px;
margin-bottom: 10px;
border-radius: 4px;
box-shadow: 0 1px 2px rgba(0,0,0,0.1);
}
terminal
#lae alla WebSocket
npm install ws
#node js allalaadimine internetist
#Serveri käivitamine
node index.js
Harjutus 12: Kuidas genereerida turvaline räsi?
Räsi (inglise keeles hash) on digitaalne sõrmejälg, mis on matemaatiliselt tuletatud allkirjastatava dokumendi bitijadast.
Räsifunktsioon (ingl. hash function) on matemaatiline funktsioon, mis kujutab väärtusi suuremast (või lõpmatust) hulgast fikseeritud väiksema võimsusega lõplikku hulka.
Lisa sinna järgnev kood:
Ava enda koodiredaktor
Tee uus fail nimega generateHash.js
const bcrypt = require('bcrypt');
const myPassword ='markiz12';
console.time('Time to generate salt');
const salt = bcrypt.genSaltSync(10);
console.log('Time to generate salt');
console.time('Time to generate hash');
const hashedPassword = bcrypt.hashSync(myPassword, salt);
console.log(myPassword+ ' is your password & this is your password after hashing it: '+ hashedPassword);
console.timeEnd('Time to generate hash');
siis terminalis paigaldame bcrypt käsuga: npm install bcrypt


Seletus:
- Real 1 laaditakse sisse bcrypt-i, mida kasutatakse paroolide krüpteerimiseks
- Real 5 loob funktsioon
genSaltSync
soola, mida kasutame real 10 räsi loomiseks. Funktsiooni sees parameeterrounds
(voorud) tähendab tegelikult kulutegurit. Kulutegur kontrollib, kui palju aega kulub ühe räsi arvutamiseks. Mida suurem on kulufaktor, seda rohkem on räsi voorusid. Vaikimisi on voorude arv 10, mis võtab kuskil 0,5 – 1 sekundit aega. Voorude arv 20 võib aga võtta juba ligi terve minuti aega. - Real 10 loob funktsioon
hashSync
räsi, koos soolaga (mille genereerisime real 5).
console.time ja console.timeEnd abil mõõdame funktsioonide aega. console.time ja console.timeEnd on paaris ning neil peab olema sama sisu (label), et leida üles paariline, kus algab või lõpeb aja mõõtmine.