Neljas praktikum - RESTful APIde loomine
Selles praktikumis loome REST API raamatute alla laadimiseks Gutenbergist (serverisse), raamatute sisu küsimiseks serverist ja raamatute haldamiseks ning sõnede otsimiseks raamatust. REST API loomiseks kasutame Python Flask raamistiku, mis pakub lihtsat liidest REST veebiteenuste loomiseks.
Viited
- Python Flask raamistik - https://flask.palletsprojects.com/en/2.0.x/
- Python Flask minimaalne näide: https://flask.palletsprojects.com/en/2.0.x/quickstart/#a-minimal-application
Probleemide korral kontrollige:
- Võimalikud probleemid ja nende potentsiaalsed lahendused osa praktikumi juhendi lõpus.
- Küsige otse
#praktikum-4-rest
Zulipi teemas.- Ka siis kui soovite lihtsalt vihjeid.
Ülesanne 4.1: Ettevalmistavad tegevused
Kasutame ka selles praktikumis Python PyCharm IDE'd. Selles ülesandes seadistame valmis Pycharm projekti ning tutvume rakenduse näitekoodiga ning sellega kuidas välja kutsuda REST GET päringuid näite programmi "vastu".
- Looge uus PyCharm Python'i projekt.
- Tõmmake alla näitekood rest_example.py
- Kasutage brauseri parem klikki ning "Save as" valikut. Siis ei lähe eesti tähed "katki"
- Tutvuge näitekoodiga
- Installeerige puuduvad paketid.
- Jooksutage programmi ja kontrollige, et see töötab korrektselt.
- Saadame
GET
päringu programmi REST API vastu pordile5000
ja ressursile/raamatud
- Tehke seda kõigepealt brauseri kaudu:
- Avage lehekülg: http://localhost:5000/raamatud
- Seejärel proovige käsurea kaudu:
- Windowsis saate kasutada PowerShell'i:
Invoke-RestMethod -Uri "http://localhost:5000/raamatud" -Method 'Get'
- Linuksis saate käsureal kasutada
curl
käsku:curl http://localhost:5000/raamatud
- Windowsis saate kasutada PowerShell'i:
- Tehke seda kõigepealt brauseri kaudu:
- Saadame
Eduka käivituse tulemusena peaks tagastama JSON objekti, mille sees on sõnum: "GET päring /raamatud REST lõpp punkti õnnestus!"
Ülesanne 4.2: REST meetod raamatute nimekirja vaatamiseks
Selles ülesandes muudame näite rakenduse REST GET meetodit nii, et see tagastaks rakenduse poolt hallatavate raamatute nimekirja (JSON andmestruktuurina). Ning valmistame (esialgu) käsitsi ette paar raamatut serverisse testimiseks.
- Looge kaust
raamatud
PyCharm projekti sees. Siia salvestab edaspidi meie programm raamatute failid. - Modifitseerige meetodit
raamatu_nimekiri()
- See meetod on serveris kätte saadav aadressil
/raamatud
,GET
REST meetodi kaudu.
- See meetod on serveris kätte saadav aadressil
- Kirjutage kood, mis genereerib nimekirja kaustas
raamatud
eksisteerivatest failidest- Failide nimekirja saamiseks saab kasutada Python meetodit:
os.listdir(kaust)
- Saate luua tühja
raamatud
listi ning sellesse lisada raamatu ID iga faili kohtaraamatu_nimekiri()
mis leidub kaustas, ning mis lõppeb .txt laiendiga- Pange listi ainult raamatu ID, eemaldades faili nime lõpust ".txt".
- Vihje: lihtne viis eemaldada ".txt" on kasutada Pythons tring split() operatsiooni, määrates eraldajaks punkti ".", ja tulemuse listist võtta vaid esimene väärtus.
- Pange listi ainult raamatu ID, eemaldades faili nime lõpust ".txt".
- Failide nimekirja saamiseks saab kasutada Python meetodit:
- Meetod peaks tagastama JSON formaadis tulemuse, mis sisaldab võtit "raamatud", mille väärtuseks on raamatute ID'de list.
- Lisaks võiks tagastada HTTP koodi "OK" (200).
- HTTP koode saab määrata return käsu teise argumendina.
- Näide:
return ({ "raamatud": raamatud }, 200 )
- Lisaks võiks tagastada HTTP koodi "OK" (200).
- Kontrollige, et tulemus on korrektne. Tehke GET päring serverisse
/raamatud
aadressil.- Testimiseks saate esialgu kausta luua uue tekst faili nimega:
12345.txt
- Või Testimiseks sinna käsitsi liigutada paar Gutenberg raamatu faili, mida olete varasemates praktikumides salvestanud.
- Näide oodatud tulemusest:
- Testimiseks saate esialgu kausta luua uue tekst faili nimega:
NB! Salvesta ülesande lahendusena ekraanivaade selle REST meetodi väljakutsumisest. Seal peaks olema näha viis, kuidas ja mis meetodit välja kutsuti (brauser või käsurida) ning tagastatud väljund.
Ülesanne 4.3: REST meetod raamatu vaatamiseks/allatõmbamiseks
Loome REST API GET meetodi, mis võimaldab alla laadida olemasoleva raamatu sisu. Meetod saab sisendiks raamatu ID, ning tagastab raamatu sisu.
- Looge uus Python meetod
raamatu_allatombamine(book_id)
:@app.route('/raamatud/<book_id>', methods = ['GET']) def raamatu_allatombamine(book_id):
- See meetod on serveris kätte saadav aadressil
/raamatud/BOOK_ID
,GET
REST meetodi kaudu. Kus BOOK_ID on raamatu Gutenberg ID.
- See meetod on serveris kätte saadav aadressil
- See meetod saab argumendiks raamatu ID (
book_id
) - Meetod peaks kontrollima, kas raamatute kaustas on sellele ID'le vastav raamatu fail
book_id.txt
- Kui ei ole sellist faili, siis peaks tagastama tühja JSON dokumendi
{}
ning HTTP koodi 404 (NOT FOUND). - Kui fail leidub, siis peaks tagastama raamatu sisu
- Faili saab meetodi tulemusena lihtsasti tagastada kasutades Flask meetodit
send_file()
- Importige see meetod:
from flask import send_file
return (send_file(faili_nimi, mimetype='text/plain'), 200)
- Kasutame HTTP koodi 200 märkimaks, et päring õnnestus.
- Kasutame
mimetype='text/plain'
määramaks, et tegemist on tavalise tekstifailiga.
- Faili saab meetodi tulemusena lihtsasti tagastada kasutades Flask meetodit
- Samuti peaks kontrollima, et meetodi argument on int tüüpi muutuja!
- On tähtis kontrollida, et päringu kaudu saadetakse korrektne sisend, muidu võib juhtuda, et kavalal ründajal õnenstub serverist mõndasid teisi faile vaadata.
- Seda saab teha näiteks nii:
not book_id.isnumeric()
- Näide oodatud tulemusest:
- Kui ei ole sellist faili, siis peaks tagastama tühja JSON dokumendi
NB! Salvesta ülesande lahendusena ekraanivaade selle REST meetodi väljakutsumisest. Seal peaks olema näha viis, kuidas ja mis meetodit välja kutsuti (brauser või käsurida) ning tagastatud väljund.
Ülesanne 4.4: REST meetod raamatu kustutamiseks
Loome REST API DELETE meetodi selleks, et saaks olemasolevaid raamatuid kustutada.
- Loome meetodi
raamatu_kustutamine(book_id)
:@app.route('/raamatud/<book_id>', methods = ['DELETE']) def raamatu_kustutamine(book_id):
- Meetodi argumendiks on raamatu ID (book_id).
- Meetodi REST tüübiks on DELETE ja REST lõpp-punktiks
/raamatud/BOOK_ID
- Meetod peaks kontrollima, kas selle ID'ga raamatu fail eksisteerib raamatu failide seas ning:
- Selle kustutama, kui see eksisteerib, ning väljastama tühja JSON struktuuri
{}
ning HTTP koodi 204. - Kui faili ei eksisteeri, peaks tagastama Tühja JSON struktuuri
{}
ning HTTP koodi 404 (Not Found).
- Selle kustutama, kui see eksisteerib, ning väljastama tühja JSON struktuuri
- Samuti peaks kontrollima, et meetodi argument on int tüüpi muutuja!
- On tähtis kontrollida, et päringu kaudu saadetakse korrektne sisend, Muidu võib juhtuda, et kavalal ründajal õnenstub serverist mõndasid teisi faile kustutada.
- Seda saab kontrollida näiteks nii:
not book_id.isnumeric()
- Kui ei ole sisendparameeter korrektne, siis peaks programm tagastama Tühja JSON struktuuri
{}
ning HTTP koodi 400 (Bad Request).
- Testige, et meetod töötab saates REST
DELETE
päring serveri REST API lõpp-punkti/raamatud/book_id
.- Windowsi näide:
Invoke-RestMethod -Uri http://localhost:5000/raamatud/12345 -Method 'Delete'
- Linuksi näide:
curl -X "DELETE" http://localhost:5000/raamatud/12345
- Windowsi näide:
- Programmi eduka töö korral kustutatakse fail.
NB! Salvesta ülesande lahendusena ekraanivaade selle REST meetodi väljakutsumisest. Seal peaks olema näha viis, kuidas ja mis meetodit välja kutsuti ning tagastatud väljund.
Ülesanne 4.5: REST meetod failide alla tõmbamiseks Gutenbergist
Loome REST API POST serveri meetodi, millele saab saata raamatu ID, mille peale server tõmbab sellele ID'le vastava raamatu Gutenberg repositooriumist alla ning salvestab raamatute kausta.
- Loome meetodi:
@app.route('/raamatud', methods = ['POST']) def raamatu_lisamine():
- See meetod on serveris kätte saadav aadressil
/raamatud
,POST
REST meetodi kaudu. - Meetodi sisuks on JSON andmestruktuur, mis sialdab raamatu Gutenberg ID'd
- Näide andmetest, mida saadetakse:
{"raamatu_id": "12345"}
- Näide meetodi välja kutsumisest:
- Windowsis:
Invoke-RestMethod -Uri "http://localhost:5000/raamatud" -Method 'Post' -Body '{"raamatu_id": "12345"}' -ContentType "application/json"
- Linuksis:
curl -X POST -H "Content-Type: application/json" --data '{"raamatu_id": "12345"}' http://localhost:5000/raamatud
- Windowsis:
- Näide andmetest, mida saadetakse:
- Meetod peaks lugema sisse raamatu ID:
input = json.loads(request.data) book_id = input['raamatu_id']
- Meetod peab alla laadima raamatu Gutenberg serverist (vastavalt raamatu ID väärtusele) ning selle salvestama raamatute kausta nimega: raamatu_id.txt
- Saate kasutada varasemate praktikumides loodud koodi raamatu alla laadimiseks Gutenbergist ning selle salvestamist failina.
- Kui õnnestub raamat alla laadida, peaks meetod peaks tagastama:
- tulemuse JSON kujul. Näide:
{"tulemus": "Raamatu loomine õnnestus", "raamatu_id": 12345 }
- HTTP koodi 201 (Created)
- tulemuse JSON kujul. Näide:
- Programmi eduka töö korral luuakse uus fail raamatute kausta.
NB! Salvesta ülesande lahendusena ekraanivaade selle REST meetodi väljakutsumisest. Seal peaks olema näha viis, kuidas ja mis meetodit välja kutsuti (brauser või käsurida) ning tagastatud väljund.
Ülesanne 4.6: REST meetod failist sõne otsimiseks
Loome REST API meetodi selleks, et saaks serveris asuvast raamatust sõnet otsida. REST meetod saab argumendiks raamatu id ja sõne ning tagastab loenduri, mis näitab mitu korda see sõne selles raamatus esines. See meetod ei tohi raamatut uuesti alla tõmmata Gutenbergist, vaid peaks otsima sõnet ainult serveris juba olevast raamatust.
- Loome meetodi:
@app.route('/raamatu_otsing', methods = ['POST']) def raamatust_sone_otsimine():
- See meetod on serveris kätte saadav aadressil
/raamatu_otsing
,POST
REST meetodi kaudu.
- See meetod on serveris kätte saadav aadressil
- Meetodi sisuks on JSON andmestruktuur, mis sialdab raamatu Gutenberg ID'd ning otsingu sõne
- Näide andmetest, mida saadetakse:
{"raamatu_id": "122", "sone": "estonia"}
- Näide meetodi välja kutsumisest:
Invoke-RestMethod -Uri "http://localhost:5000/raamatu_otsing" -Method 'Post' -Body '{"raamatu_id": "122", "sone": "estonia"}' -ContentType "application/json"
- Näide andmetest, mida saadetakse:
- Meetod peaks lugema sisse raamatu ID:
input = json.loads(request.data) sone = input['sone'] raamatu_id = input['raamatu_id']
- Meetod peab avama vastava raamatu faili ning, sealt otsima määratud sõne leidumist ning arvutama kokku, mitu korda see sõne seal leidus
- Saate kasutada varasemate praktikumides loodud koodi raamatust sõne otsimiseks. Aga kindlasti peab otsima juba alla laetud failist raamatute kaustas.
- Kui raamat leidub, peaks meetod peaks tagastama:
- tulemuse JSON kujul. Näide:
{"raamatu_id": 122, "sone": "and", "leitud": 226 }
- HTTP koodi 200 (OK)
- tulemuse JSON kujul. Näide:
- Kui raamatut ei leidu, siis tuleks tagastada HTTP kood 404 (Not Found) ja tühi JSON
{}
NB! Salvesta ülesande lahendusena ekraanivaade selle REST meetodi väljakutsumisest. Seal peaks olema näha viis, kuidas ja mis meetodit välja kutsuti (käsurida) ning tagastatud väljund.
Lahenduse esitamine
Praktikumi lahendusena tuleb esitada:
- Python kood, mis valmis praktikumi lõpuks.
- NB! Ei pea iga ülesande lahendust eraldi salvestama.
- Ekraanivaated ülesannetest 4.2-4.6.
- Failid tuleks kokku pakkida üheks Zip failiks enne üles laadimist.
- Lahendusega ei tohi kaasa panna virtuaalkeskkonna kaustasid (nt. .venv, .env, venv)