Projektovanje informacionih sistema · Poglavlje 10 · Sedmica 10

Integracija i API

Dio 1 – HTTP i REST

Dio 2 – JSON i OpenAPI

Dio 3 – Događaji i vanjski servisi

Praksa – Mali FastAPI server; HTTPie

Materijale priredio Erkan Islamović

erkan.islamovic@eubd.edu.ba · erkan.islamovic@gmail.com

Šta učimo ovog semestra

Petnaest sedmica, svaka s tri časa teorije i tri časa prakse. Danas: poglavlje 10 (Sedmica 10, označeno). Isti primjer kroz knjigu: DeliveryApp, narudžba N-1001 (24,50 €).

Sed.PoglavljeSed.Poglavlje
1P1 Zašto projektujemo9P9 Arhitektura
2P2 Životni ciklus10P10 Integracija i API
3P3 Zahtjevi11P11 Korisnički interfejs
4P4 Poslovni procesi12P12 Sigurnost i privatnost
5P5 UML i slučajevi korištenja13P13 Realno vrijeme i IoT
6P6 Klase i objekti14P14 Kvalitet i isporuka
7P7 Sekvence i stanja15P15 AI i završni projekat
8P8 Baza podataka
Mermaid crta · Python izvršava · SQLite čuva · Git pamti verzije

Literatura

  1. B. Popović, K. Kuk: Informacioni sistemi, Kriminalističko-policijski univerzitet, Beograd, 2017.
  2. J. S. Valacich, J. F. George: Modern Systems Analysis and Design, 9th ed., Pearson, 2020.
  3. L. Jelenković: Sustavi za rad u stvarnom vremenu – skripta, FER, Zagreb, 2015.
  4. D. Milićev: Programiranje u realnom vremenu – skripta, Beograd, 2002.
  5. V. Kovačević, M. Popović: Sistemska programska podrška u realnom vremenu 1, FTN, Novi Sad, 2013.

Priča za početak

Priča za početak

U decembru 1998. godine NASA je lansirala letjelicu Mars Climate Orbiter, koja je trebala kružiti oko Marsa i proučavati njegovu atmosferu. Na putu, koji je trajao devet mjeseci, letjelica je povremeno palila male motore da ispravi putanju. Podatke o tim paljenjima računao je softver na Zemlji koji je napravila firma Lockheed Martin, a navigaciju je vodio tim NASA-ine laboratorije JPL. Dogovor je bio da se jačina paljenja šalje u njutn-sekundama, metričkoj jedinici. Ali jedan program je slao brojeve u funta-sila sekundama, američkoj jedinici. Jedna funta-sila sekunda je oko 4,45 njutn-sekundi, pa je navigacija svaki put četiri i po puta potcijenila koliko je motor gurnuo letjelicu. Greška se gomilala mjesecima. U septembru 1999. letjelica je prišla Marsu mnogo niže nego što je trebalo i izgubljena je u njegovoj atmosferi. Istražna komisija je kao glavni uzrok navela upravo ovu neusklađenost jedinica između dva programa. Oba programa su, svaki za sebe, „radila”. Pogriješio je dogovor između njih, a taj dogovor danas zovemo interfejs ili API.

Zašto ovo poglavlje

U poglavlju 9 nacrtali smo kontejnere DeliveryApp: mobilnu aplikaciju, web aplikaciju restorana, API server, bazu, red poruka i servis obavještenja, uz vanjski sistem plaćanja i servis mapa. Strelice između njih nosile su natpise kao „JSON preko HTTPS”. Ovo poglavlje objašnjava šta te strelice znače i kako se dogovor između dijelova piše tako da se ne desi greška kao s jedinicama na Marsu. Prvo učimo HTTP i REST, jezik kojim aplikacija razgovara sa serverom. Zatim JSON i OpenAPI, kojim se dogovor zapisuje kao ugovor. Na kraju događaje, redove poruka i povezivanje s vanjskim sistemima koji ponekad ne odgovaraju. Na praktičnoj nastavi pokrećemo pravi mali server DeliveryApp u Pythonu i šaljemo mu zahtjeve.

Riječi ovog poglavlja (1/3)

  • API (application programming interface) – dogovoren način na koji jedan program traži uslugu od drugog.
  • Integracija – povezivanje više sistema tako da razmjenjuju podatke i rade zajedno.
  • HTTP – protokol (pravila razgovora) kojim preglednici i aplikacije razgovaraju sa serverima na webu.
  • Zahtjev i odgovor – klijent šalje zahtjev (metoda, adresa, podaci), server vraća odgovor (statusni kod, podaci).
  • Metoda – vrsta zahtjeva: GET čita, POST pravi, PATCH mijenja dio, PUT zamjenjuje, DELETE briše.
  • Statusni kod – trocifren broj u odgovoru koji kaže kako je prošlo (200 uspjeh, 404 nema, 500 greška servera).

Riječi ovog poglavlja (2/3)

  • REST – stil projektovanja API-ja u kojem su podaci „resursi” s adresama, a radnje su HTTP metode.
  • JSON – jednostavan tekstualni format za podatke: imena i vrijednosti u vitičastim zagradama.
  • OpenAPI – standard za opis API-ja kao ugovora: adrese, metode, ulazi, izlazi i greške.
  • Idempotentnost – osobina da ponovljen isti zahtjev ima isti efekat kao jedan.
  • Webhook – poziv koji vanjski sistem sam pošalje našem serveru kad se nešto desi (npr. plaćanje odobreno).
  • Događaj – zapis da se nešto desilo („narudžba N-1001 je spremna”), koji se šalje onima koje zanima.

Riječi ovog poglavlja (3/3)

  • Vremensko ograničenje (timeout) – koliko najduže čekamo odgovor prije nego što odustanemo.
  • Verzija API-ja – oznaka (npr. /v1/) koja omogućava da se API mijenja bez rušenja starih aplikacija.

Ciljevi poglavlja

Nakon poglavlja možete:

objasniti šta je API i zašto je dogovor između sistema najosjetljiviji dio integracije; opisati HTTP zahtjev i odgovor; izabrati pravu HTTP metodu i statusni kod; projektovati REST adrese za resurse DeliveryApp; pročitati i napisati JSON za narudžbu, s jasnim jedinicama; pročitati OpenAPI specifikaciju i objasniti zašto se piše prije koda; objasniti verzionisanje i kompatibilnost API-ja; razlikovati sinhronu integraciju, webhook i red poruka; projektovati poziv vanjskog servisa s vremenskim ograničenjem, ponovnim pokušajem i idempotentnim ključem; pokrenuti FastAPI server DeliveryApp i poslati mu zahtjeve iz HTTPie.

Plan poglavlja – Sedmica 10: tri časa teorije i tri časa praktične nastave

ČasSadržajNa času
Teorija 110.1–10.3 API, HTTP, RESTŠalter s jelovnikom; pet adresa DeliveryApp
Teorija 210.4–10.6 JSON, jedinice, OpenAPI, verzijeMars 1999: 4,45 puta; ugovor prije koda
Teorija 310.7–10.9 Webhook, događaji, vanjski servisi, sigurnostKako se kartica ne naplati dvaput
Praksa 1–3FastAPI server; HTTPie; /docs; OpenAPI201, 422, 409 i 24,50 €
Dio 1 · Sedmica 10

Dio 1 – HTTP i REST

10.1 Šta je API

API (od engleskog application programming interface, programski interfejs aplikacije) je dogovoren način na koji jedan program traži uslugu od drugog. Mobilna aplikacija DeliveryApp ne zna kako server računa dostavu, kako izgleda baza, ni u kojem je jeziku server napisan. Zna samo dogovor: „pošalji ovakav zahtjev na ovu adresu i dobićeš ovakav odgovor”.

Slika iz života: šalter s jelovnikom u restoranu brze hrane. Gost ne ulazi u kuhinju. Na šalteru piše šta se može naručiti, kako (broj menija) i šta se dobija. Kuhinja može promijeniti peć, kuhara ili raspored, a gost i dalje naručuje isto. API je taj šalter: sakriva unutrašnjost i obećava šta se dobija.

To obećanje je ugovor. Ako se jedna strana ne drži ugovora, sistem se kvari, iako je svaki dio sam za sebe ispravan, kao kod letjelice na Marsu. Zato je projektovanje API-ja jedna od najvažnijih arhitektonskih odluka: mobilne aplikacije na hiljadama telefona zavise od njega i ne mogu se sve promijeniti preko noći.

Ukratko – 10.1 Šta je API

  • API je dogovoren način na koji jedan program traži uslugu od drugog.
  • Kao šalter s jelovnikom: sakriva kuhinju i obećava šta se dobija.
  • API je ugovor; ako ga jedna strana prekrši, sistem se kvari iako je svaki dio ispravan.

10.2 HTTP: zahtjev i odgovor

Dijelovi DeliveryApp razgovaraju preko interneta protokolom HTTP (Hypertext Transfer Protocol), istim kojim preglednik otvara web stranice. Protokol je skup pravila razgovora, kao bonton telefonskog poziva. U HTTP-u razgovor je uvijek isti: klijent pošalje zahtjev, server vrati odgovor.

Zahtjev ima četiri dijela:

  1. metodu – šta želimo uraditi;
  2. adresu (URL) – nad čim, npr. /v1/narudzbe/N-1001;
  3. zaglavlja – dodatne informacije, npr. u kojem formatu šaljemo i ko smo (token za prijavu);
  4. tijelo – podaci, ako ih šaljemo (npr. stavke narudžbe).

Odgovor ima statusni kod, zaglavlja i tijelo.

10.2 HTTP: zahtjev i odgovor

HTTP metode

10.2 HTTP: zahtjev i odgovor

MetodaŠta radiPrimjer u DeliveryApp
GETčita, ne mijenja ništapročitaj jelovnik restorana R-1
POSTpravi nešto novonapravi narudžbu
PATCHmijenja dio postojećegpromijeni stanje narudžbe u PRIHVAĆENA
PUTzamjenjuje cijelo postojećezamijeni cijeli jelovnik
DELETEbrišeukloni jelo s jelovnika

10.2 HTTP: zahtjev i odgovor

Statusni kodovi

Statusni kod je trocifren broj čija prva cifra kaže grupu: 2xx uspjeh, 4xx greška klijenta (zahtjev nije dobar), 5xx greška servera.

10.2 HTTP: zahtjev i odgovor

KodZnačenjeKada ga DeliveryApp vraća
200 OKuspjehjelovnik je pročitan, cijena izračunata
201 Creatednapravljenonova narudžba N-1001
400 Bad Requestzahtjev je pokvarentijelo nije ispravan JSON
401 Unauthorizedniste prijavljeninema tokena za prijavu
403 Forbiddenprijavljeni ste, ali nemate pravokupac pokušava promijeniti stanje narudžbe
404 Not Foundne postojinarudžba N-9999
409 Conflictsukob sa stanjemotkazivanje narudžbe u pripremi (PP-6)
422 Unprocessable Contentpodaci su čitljivi, ali krše praviloadresa 11 km (PP-3), iznos 4,50 € (PP-1)
500 Internal Server Errorgreška u našem koduizuzetak koji nismo predvidjeli
503 Service Unavailableserver privremeno ne možepreopterećenje ili održavanje

10.2 HTTP: zahtjev i odgovor

Dobar API vraća pravi statusni kod i kratku poruku. Loš API na sve vraća 200 i u tijelu piše „greška”, pa aplikacija mora čitati tekst da bi saznala da nešto nije u redu.

Slika 10.1 – HTTP zahtjev i odgovor: izračun cijene za N-1001
Slika 10.1 – HTTP zahtjev i odgovor: izračun cijene za N-1001

Ukratko – 10.2 HTTP: zahtjev i odgovor

  • HTTP je protokol u kojem klijent šalje zahtjev, a server vraća odgovor.
  • Zahtjev ima metodu, adresu, zaglavlja i tijelo; odgovor ima statusni kod, zaglavlja i tijelo.
  • GET čita, POST pravi, PATCH mijenja dio, PUT zamjenjuje, DELETE briše.
  • Statusni kodovi 2xx su uspjeh, 4xx greška klijenta, 5xx greška servera; 409 i 422 DeliveryApp vraća za kršenje pravila.

10.3 REST: resursi s adresama

Kako izabrati adrese i metode? Najrašireniji stil zove se REST (representational state transfer). Ideja je jednostavna: podaci se vide kao resursi, svaki resurs ima svoju adresu, a radnje su HTTP metode. Adrese su imenice u množini, a ne glagoli.

API DeliveryApp, verzija 1:

10.3 REST: resursi s adresama

Metoda i adresaŠta radiUspjehGreške
GET /v1/jela?restoran=R-1jela jednog restorana200–
POST /v1/cijenaizračunaj cijenu (ne čuva ništa)200422
POST /v1/narudzbenapravi narudžbu u stanju NOVA201404, 422
GET /v1/narudzbe/N-1001pročitaj narudžbu200404
PATCH /v1/narudzbe/N-1001/stanjepromijeni stanje200404, 409

Primijetite dvije stvari. Prvo, ove adrese su upravo strelice prema serveru iz sekvencijalnog dijagrama (poglavlje 7): izracunaj_cijenu je postala POST /v1/cijena, a napravi_narudzbu je postala POST /v1/narudzbe. Drugo, PATCH …/stanje ne postavlja stanje „na silu”: server poziva promijeni() iz poglavlja 7, i ako prelaz nije u tabeli, vraća 409 Conflict. Tabela prelaza je tako zaštićena i na nivou API-ja.

10.3 REST: resursi s adresama

Idempotentnost

Mobilna mreža je nepouzdana. Kupac pritisne „Naruči”, zahtjev ode, ali odgovor se izgubi u tunelu. Aplikacija ne zna je li narudžba napravljena, pa pošalje zahtjev ponovo. Hoće li kupac dobiti dvije narudžbe i dvije naplate?

Ovdje pomaže pojam idempotentnosti: zahtjev je idempotentan ako ponavljanje ima isti efekat kao jedan zahtjev. GET je idempotentan (čitanje dvaput ništa ne mijenja). PATCH stanje=PRIHVAĆENA je idempotentan u smislu da je narudžba poslije oba poziva prihvaćena. POST /v1/narudzbe nije: svaki poziv pravi novu narudžbu. Kako se to rješava, vidjećemo u 10.8.

Ukratko – 10.3 REST: resursi s adresama

  • REST vidi podatke kao resurse s adresama, a radnje kao HTTP metode; adrese su imenice u množini.
  • API DeliveryApp v1 ima pet adresa, nastalih iz poruka sekvencijalnog dijagrama.
  • PATCH stanja poziva mašinu stanja i za nedozvoljen prelaz vraća 409.
  • Idempotentan zahtjev ima isti efekat ponovljen kao jednom; POST za narudžbu to nije.

Provjeri se

  1. Koju metodu koristimo za čitanje jelovnika? GET.
  2. Koji statusni kod vraća server kad kupac naruči na 11 km? 422, jer zahtjev krši pravilo PP-3.
  3. Zašto POST /v1/narudzbe nije idempotentan? Jer svaki ponovljeni poziv pravi novu narudžbu.

Odgovori: tipka R ili klik na zamućeno polje.

Dio 2 · Sedmica 10

Dio 2 – JSON, ugovor i verzije

10.4 JSON i jedinice

Podaci u zahtjevu i odgovoru najčešće se šalju u formatu JSON (JavaScript Object Notation, čita se „džejson”). JSON je običan tekst s malo pravila: objekat je u vitičastim zagradama i ima parove "ime": vrijednost; niz je u uglastim zagradama; vrijednosti su tekst (pod navodnicima), broj, true/false ili null.

Zahtjev za cijenu N-1001:

{
  "kupac": "K-01",
  "udaljenost_km": 4.2,
  "stavke": [
    {"jelo_id": 1, "kolicina": 2},
    {"jelo_id": 3, "kolicina": 1}
  ]
}

Odgovor servera:

10.4 JSON i jedinice

{
  "artikli": 2150,
  "popust": 0,
  "dostava": 300,
  "ukupno": 2450,
  "valuta": "EUR",
  "jedinica": "cent"
}

U JSON-u se, kao u svakom kodu, piše decimalna tačka (4.2). A sada najvažnija lekcija ovog poglavlja, ona s Marsa: broj bez jedinice je opasan. Šta znači "dostava": 300? Tri stotine eura? Tri eura? Zato dobar API jedinicu stavlja u ime polja (udaljenost_km) ili u odgovor ("jedinica": "cent"), i obavezno u ugovor (10.5).

Ista pravila važe za druge vrste podataka koje se često pokvare između sistema:

10.4 JSON i jedinice

PodatakOpasnostDogovor DeliveryApp
novaceur ili centi? decimalni zarez ili tačka?cijeli broj centi, polje valuta
udaljenostkm ili milje?km, u imenu polja
vrijemekoja vremenska zona? 03/04 je mart ili april?ISO 8601 u UTC: 2026-10-02T10:10:00Z
tekstkodiranje slova č, ć, žUTF-8
stanje„Prihvacena”, „prihvaćena”, „ACCEPTED”?tačno jedna od sedam vrijednosti iz poglavlja 7

10.4 JSON i jedinice

Iz stvarnog svijeta

Komisija za Mars Climate Orbiter zaključila je 1999. da se greška u jedinicama mogla otkriti, ali da provjere interfejsa između dva programa nisu bile dovoljne. Pouka za svakog projektanta: u ugovoru između sistema svaki broj ima jedinicu, a test provjerava i jedinicu, ne samo da je broj stigao.

Ukratko – 10.4 JSON i jedinice

  • JSON je tekstualni format s objektima, nizovima, tekstom, brojevima, true/false i null.
  • U JSON-u se piše decimalna tačka.
  • Broj bez jedinice je opasan: jedinica ide u ime polja, u odgovor i u ugovor.
  • DeliveryApp šalje novac u centima, udaljenost u km, vrijeme u ISO 8601 (UTC) i tekst u UTF-8.

10.5 OpenAPI: ugovor prije koda

Ugovor API-ja može se opisati riječima u dokumentu, ali tada ga ljudi i programi čitaju različito. Zato postoji standard OpenAPI: opis API-ja u formatu YAML ili JSON koji kaže, za svaku adresu, koje metode postoje, šta se šalje, šta se vraća i koje greške su moguće. Dio ugovora DeliveryApp (cijeli fajl je primjeri/deliveryapp/openapi.yaml):

openapi: 3.1.0
info:
  title: DeliveryApp API
  version: 1.0.0
paths:
  /v1/cijena:
    post:
      summary: Izračunaj cijenu narudžbe (ništa se ne čuva)
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/NarudzbaUlaz"
      responses:
        "200":
          description: Obračun po pravilima PP-1 do PP-5
        "422":
          description: Narudžba krši PP-1 ili PP-3 (premala ili izvan zone)
components:
  schemas:
    NarudzbaUlaz:
      type: object
      required: [kupac, udaljenost_km, stavke]
      properties:
        udaljenost_km: { type: number, description: "udaljenost u kilometrima", example: 4.2 }
        stavke:
          type: array
          minItems: 1

YAML je format sličan JSON-u, ali bez zagrada: uvlačenje redova pokazuje šta je unutar čega. Ovaj opis čitaju i ljudi i programi:

10.5 OpenAPI: ugovor prije koda

  • iz njega se automatski pravi dokumentacija s dugmetom „probaj” (FastAPI je pravi sam, na adresi /docs);
  • iz njega se može automatski napraviti kod klijenta za mobilnu aplikaciju;
  • iz njega se prave testovi ugovora, koji provjeravaju da server vraća baš ono što ugovor kaže.

Pristup u kojem se ugovor napiše i dogovori prije pisanja koda zove se API-first (prvo API). Tim mobilne aplikacije i tim servera tada mogu raditi istovremeno: obje strane znaju ugovor, a mobilni tim do završetka servera koristi lažni server koji vraća primjere iz ugovora. To je upravo ono što je nedostajalo kod Healthcare.gova (poglavlje 1), gdje su dijelovi različitih firmi zajedno isprobani tek na kraju.

Ukratko – 10.5 OpenAPI: ugovor prije koda

  • OpenAPI je standard za opis API-ja kao ugovora: adrese, metode, ulazi, izlazi i greške.
  • Iz OpenAPI opisa automatski nastaju dokumentacija, kod klijenta i testovi ugovora.
  • Pristup API-first piše ugovor prije koda, pa timovi mogu raditi istovremeno.
  • YAML je format sličan JSON-u u kojem uvlačenje pokazuje strukturu.

10.6 Verzije i kompatibilnost

Kad je API jednom objavljen, na njega se oslanjaju aplikacije na hiljadama telefona, i to i one stare, koje kupci mjesecima ne ažuriraju. Zato se API mijenja pažljivo.

Promjene se dijele na dvije vrste:

  • Kompatibilne (ne ruše stare klijente): dodavanje novog polja u odgovor (stari klijent ga ignoriše), dodavanje nove adrese, dodavanje opcionog polja u zahtjev.
  • Nekompatibilne (ruše stare klijente): brisanje ili preimenovanje polja, promjena tipa (iznos iz centi u eure s decimalama!), promjena značenja statusnog koda, novo obavezno polje u zahtjevu.

Za nekompatibilne promjene pravi se nova verzija: /v2/narudzbe, dok /v1/ radi dalje neko vrijeme, uz najavu kada će biti ugašena. Zato adrese DeliveryApp od početka počinju sa /v1/.

Česta zabluda

„Samo ćemo preimenovati ukupno u ukupno_centi, to je sitnica.” Za server jeste. Za svaku staru aplikaciju koja traži polje ukupno, cijena je odjednom prazna, pa kupac vidi „0,00 €” ili aplikacija padne. Sitna promjena u ugovoru nije sitna za one koji ga se drže.

Ukratko – 10.6 Verzije i kompatibilnost

  • Kompatibilne promjene (novo polje, nova adresa) ne ruše stare klijente.
  • Nekompatibilne promjene (brisanje, preimenovanje, promjena tipa) traže novu verziju API-ja.
  • Adrese počinju sa /v1/, da bi nova verzija mogla raditi uporedo sa starom.

Provjeri se

  1. Zašto polje u JSON-u treba nositi jedinicu? Jer broj bez jedinice različiti programi mogu shvatiti različito, kao funte i njutne na Marsu.
  2. Šta automatski nastaje iz OpenAPI opisa? Dokumentacija, kod klijenta i testovi ugovora.
  3. Je li dodavanje novog polja u odgovor kompatibilna promjena? Da; stari klijent ga ignoriše.

Odgovori: tipka R ili klik na zamućeno polje.

Dio 3 · Sedmica 10

Dio 3 – Integracija s drugim sistemima

10.7 Tri načina razgovora

Dijelovi sistema razgovaraju na tri osnovna načina, a dobar projektant za svaku strelicu bira pravi:

  1. Sinhroni poziv (zahtjev–odgovor): pozivalac čeka odgovor. Aplikacija pita server za cijenu i čeka. Jednostavno, ali pozivalac stoji dok druga strana ne odgovori, a ako druga strana ne radi, ne radi ni pozivalac.
  2. Webhook (povratni poziv): naš server da vanjskom sistemu adresu i kaže „javi mi kad se nešto desi”. Sistem plaćanja, kad banka odobri karticu, sam pošalje POST na našu adresu /v1/placanja/potvrda. Ne moramo ga pitati svakih pet sekundi „je li plaćeno?”.
  3. Događaji preko reda poruka (asinhrono): server objavi događaj („narudžba N-1001 je spremna”) u red poruka i odmah nastavi. Ko god je zainteresovan (servis obavještenja, izvještaji) uzme događaj kad stigne. Pošiljalac ne mora ni znati ko sve sluša.

Slika iz života: sinhroni poziv je telefonski razgovor, webhook je „nazvaću vas kad bude gotovo” u servisu za auto, a red poruka je oglasna tabla u hodniku: objavite obavještenje, a svako ko prođe pročita ga kad stigne.

10.7 Tri načina razgovora

Strelica u DeliveryAppNačinZašto
aplikacija → server: cijenasinhronokupac mora vidjeti cijenu odmah
server → servis mapa: udaljenostsinhronobez udaljenosti nema cijene
sistem plaćanja → server: potvrdawebhookbanka odgovara za nekoliko sekundi; ne čekamo
server → servis obavještenja: „spremna”događaj u reduobavještenje ne smije usporiti restoran
server → izvještaji: „isporučena”događaj u reduizvještaj se računa kasnije, svojim tempom
Slika 10.2 – Tri načina razgovora: sinhroni poziv, webhook i red poruka
Slika 10.2 – Tri načina razgovora: sinhroni poziv, webhook i red poruka

Ukratko – 10.7 Tri načina razgovora

  • Sinhroni poziv čeka odgovor; webhook je poziv koji nam vanjski sistem pošalje kad se nešto desi; događaj u redu poruka čita ko je zainteresovan.
  • Kao telefonski razgovor, „nazvaću vas” i oglasna tabla.
  • Za cijenu i udaljenost DeliveryApp koristi sinhroni poziv, za potvrdu plaćanja webhook, a za obavještenja i izvještaje red poruka.

10.8 Kad vanjski sistem kasni ili ne odgovara

Vanjski sistemi (servis mapa, sistem plaćanja) nisu pod našom kontrolom. Nekad kasne, nekad ne odgovore, nekad odgovore dvaput. Dobra integracija to očekuje i ima tri alata.

1. Vremensko ograničenje (timeout). Nikad se ne čeka zauvijek. Specifikacija UC-01 kaže: ako servis mapa ne odgovori za 10 sekundi, kupac vidi poruku i ne može platiti (alternativni tok 3a, poglavlje 5). Bez ograničenja, jedan spor vanjski servis zauzme sve niti servera i DeliveryApp prestane odgovarati svima.

2. Ponovni pokušaj s pauzom (retry with backoff). Mnoge greške su prolazne: mreža je na trenutak pala. Zato se poziv ponovi, ali ne odmah i ne beskonačno: npr. poslije 1 s, pa 2 s, pa 4 s (pauza se svaki put udvostruči), najviše tri puta. Zbir čekanja je tada 1 + 2 + 4 = 7 sekundi. Udvostručavanje sprečava da hiljade klijenata u istom trenutku zatrpa servis koji se tek oporavlja.

3. Idempotentni ključ. Ponovni pokušaj je opasan za plaćanje. Ako je prvi zahtjev „naplati 24,50 €” stigao do banke, a samo se odgovor izgubio, drugi pokušaj bi naplatio još jednom. Rješenje: uz svaki zahtjev za naplatu šalje se jedinstven idempotentni ključ (npr. N-1001-placanje-1). Sistem plaćanja pamti ključeve: ako stigne isti ključ drugi put, ne naplaćuje ponovo, nego vrati rezultat prvog pokušaja. Isti trik štiti i POST /v1/narudzbe od duple narudžbe iz 10.3: aplikacija šalje ključ, a server s istim ključem ne pravi drugu narudžbu.

10.8 Kad vanjski sistem kasni ili ne odgovara

Slika iz života za idempotentni ključ: broj na računu u restoranu. Ako konobar dvaput donese isti račun broj 4711, platite jednom, jer je to isti račun.

Za radoznale

Ako vanjski servis stalno pada, nema smisla svaki zahtjev slati ponovo. Obrazac prekidač kola (circuit breaker) poslije nekoliko uzastopnih grešaka „isključi” poziv na neko vrijeme i odmah vraća grešku ili rezervni odgovor (npr. „dostava će biti obračunata pri preuzimanju”), a zatim povremeno proba da li se servis oporavio. Ime dolazi od osigurača u kući, koji iskoči da ne bi izgorjela instalacija.

Ukratko – 10.8 Kad vanjski sistem kasni ili ne odgovara

  • Vanjski sistemi kasne i padaju; dobra integracija to očekuje.
  • Vremensko ograničenje sprečava da spor servis zaustavi naš sistem.
  • Ponovni pokušaj s udvostručenom pauzom (1, 2, 4 s) rješava prolazne greške.
  • Idempotentni ključ sprečava da se kartica naplati dvaput ili narudžba napravi dvaput.

10.9 API i sigurnost, ukratko

API je vrata sistema, pa ga moraju čuvati brave. Detaljno o sigurnosti govori poglavlje 12, a za API su najvažnije četiri stvari:

  1. HTTPS, nikad HTTP. Sav saobraćaj je šifrovan, da niko na putu (npr. na javnoj Wi-Fi mreži) ne pročita adresu ni token kupca.
  2. Prijava tokenom. Poslije prijave aplikacija dobija token, dugačak niz znakova koji šalje uz svaki zahtjev (zaglavlje Authorization). Server iz tokena zna ko je i koju ulogu ima.
  3. Provjera prava na svakom zahtjevu. Kupac smije čitati svoje narudžbe, ali ne i tuđe; samo restoran smije narudžbu prihvatiti. Česta greška je provjeriti samo da je korisnik prijavljen, a ne i da je narudžba N-1001 baš njegova; tada kupac K-02 mijenjanjem broja u adresi čita tuđe narudžbe.
  4. Ograničenje broja zahtjeva (rate limiting). Jedan klijent smije, na primjer, najviše 60 zahtjeva u minuti; više dobija 429 Too Many Requests. Tako se jedan pokvaren ili zlonamjeran klijent ne može srušiti sistem za sve.

Ukratko – 10.9 API i sigurnost, ukratko

  • API se poziva samo preko HTTPS-a.
  • Klijent se predstavlja tokenom koji šalje uz svaki zahtjev.
  • Server na svakom zahtjevu provjerava da li korisnik smije baš ovu radnju nad baš ovim podatkom.
  • Ograničenje broja zahtjeva štiti sistem od jednog pokvarenog ili zlonamjernog klijenta.

Provjeri se

  1. Kojim načinom sistem plaćanja javlja da je plaćanje odobreno? Webhookom: sam pošalje zahtjev na našu adresu.
  2. Koliko ukupno čekamo kod tri ponovna pokušaja s pauzama 1, 2 i 4 s? 7 sekundi.
  3. Čemu služi idempotentni ključ kod plaćanja? Da ponovljeni zahtjev ne naplati karticu još jednom.

Odgovori: tipka R ili klik na zamućeno polje.

Praksa · Sedmica 10

Praktična nastava – mali server DeliveryApp

Praktična nastava – mali server DeliveryApp

Cilj je pokrenuti pravi API server DeliveryApp u Pythonu, poslati mu zahtjeve iz HTTPie i preglednika, pročitati automatsku OpenAPI dokumentaciju i proširiti API jednom adresom. Radi se u folderu kod/.

Korak 1 – Instalacija i pokretanje

  1. U terminalu, u folderu kod/:
pip install fastapi uvicorn httpie
  1. Kopirajte api.py i openapi.yaml iz primjeri/deliveryapp/ (uz deliveryapp.py koji već imate).
  2. Pokrenite server:
uvicorn api:app --reload
  1. Otvorite u pregledniku http://127.0.0.1:8000/docs. FastAPI je sam napravio dokumentaciju iz koda, po standardu OpenAPI. Otvorite POST /v1/cijena, kliknite Try it out i pošaljite primjer.

Korak 2 – Zahtjevi iz HTTPie

U drugom terminalu pošaljite (HTTPie sam pretvara ime=vrijednost u JSON; := znači broj ili JSON, a ne tekst):

http GET :8000/v1/jela restoran==R-1
http POST :8000/v1/cijena kupac=K-01 udaljenost_km:=4.2 stavke:='[{"jelo_id":1,"kolicina":2},{"jelo_id":3,"kolicina":1}]'

Očekivani odgovor drugog zahtjeva:

HTTP/1.1 200 OK
{
    "artikli": 2150,
    "dostava": 300,
    "jedinica": "cent",
    "popust": 0,
    "ukupno": 2450,
    "valuta": "EUR"
}

Korak 3 – Narudžba i stanja

  1. Napravite narudžbu: isti zahtjev kao u koraku 2, ali POST :8000/v1/narudzbe. Očekivano: 201 Created i "broj": "N-1001", "stanje": "NOVA".
  2. Promijenite stanje:
http PATCH :8000/v1/narudzbe/N-1001/stanje stanje=PRIHVAĆENA
http PATCH :8000/v1/narudzbe/N-1001/stanje stanje=U_PRIPREMI
http PATCH :8000/v1/narudzbe/N-1001/stanje stanje=OTKAZANA

Prva dva vraćaju 200. Treći vraća 409 Conflict s porukom nedozvoljen prelaz U_PRIPREMI -> OTKAZANA: pravilo PP-6 čuva API.

  1. Pročitajte narudžbu (http GET :8000/v1/narudzbe/N-1001) i pogledajte polje istorija.

Korak 4 – Greške po pravilima

Pošaljite i zapišite statusni kod i poruku za: narudžbu na 11 km; narudžbu s jednom voćnom salatom (4,50 €); stavku s količinom 0; nepostojeće jelo 99; narudžbu N-9999. Uporedite s tabelom statusnih kodova iz 10.2: koji kod biste vi izabrali za svaki slučaj, i da li se slaže s onim što server vraća?

Korak 5 – Nova adresa

Dodajte u api.py adresu GET /v1/narudzbe?kupac=K-01 koja vraća sve narudžbe jednog kupca. Zatim dopišite istu adresu u openapi.yaml. Provjerite u /docs da se pojavila i pošaljite joj zahtjev iz HTTPie. Razmislite: je li ova promjena kompatibilna s verzijom v1? (Jeste: nova adresa ne ruši stare klijente.)

Korak 6 – AI kao recenzent ugovora (opcionalno)

Dajte AI asistentu svoj openapi.yaml i zatražite: „Pronađi polja bez jedinice ili opisa, i greške koje API ne opisuje.” Svaku primjedbu provjerite i ispravite u ugovoru. Zatražite i HTTPie naredbe za sve greške iz koraka 4, pa ih pokrenite i provjerite da AI nije pogodio pogrešan statusni kod.

Rezultat koji se predaje: kod/api.py s novom adresom, dopunjen kod/openapi.yaml, i fajl kod/zahtjevi.md s naredbama iz koraka 2 do 5 i stvarnim odgovorima servera (statusni kodovi i tijela).

Vježbe

Vježbe za studenta

Rješenja su sakrivena – tipka R ili klik na okvir.

Vježba za studenta 1 – metoda i kod.

Zadatak

Za svaku radnju napišite metodu, adresu i statusni kod uspjeha: a) restoran označi Capricciosu kao nedostupnu; b) kupac pročita svoju narudžbu N-1002; c) administrator doda restoran R-4; d) restoran ukloni jelo 6 s jelovnika.

Vježba za studenta 1 – metoda i kod. – rješenje

Rješenje (R)

a) PATCH /v1/jela/2 s tijelom {"dostupno": false}, 200. b) GET /v1/narudzbe/N-1002, 200. c) POST /v1/restorani, 201. d) DELETE /v1/jela/6, 204 (No Content) ili 200.

Vježba za studenta 2 – statusni kod greške.

Zadatak

Koji kod treba vratiti? a) kupac nije poslao token; b) kupac K-02 pokušava pročitati N-1001 kupca K-01; c) tijelo zahtjeva nije ispravan JSON; d) restoran pokušava prihvatiti već isporučenu narudžbu; e) baza je pala.

Vježba za studenta 2 – statusni kod greške. – rješenje

Rješenje (R)

a) 401; b) 403 (ili 404, ako ne želimo otkriti da narudžba postoji); c) 400; d) 409, jer prelaz ISPORUČENA → PRIHVAĆENA nije dozvoljen; e) 503 (ili 500).

Vježba za studenta 3 – JSON s jedinicama.

Zadatak

Napišite JSON odgovor servera na GET /v1/narudzbe/N-1002 (4 × Ćevapi, 2,5 km, stanje NA_PUTU, dostavljač D-3), s jedinicama u imenima polja ili posebnim poljem.

Vježba za studenta 3 – JSON s jedinicama. – rješenje

Rješenje (R)

Na primjer:

{
  "broj": "N-1002",
  "kupac": "K-02",
  "restoran": "R-2",
  "stanje": "NA_PUTU",
  "dostavljac": "D-3",
  "udaljenost_km": 2.5,
  "artikli": 3200,
  "dostava": 0,
  "ukupno": 3200,
  "valuta": "EUR",
  "jedinica": "cent",
  "vrijeme": "2026-10-02T10:25:00Z"
}

Vježba za studenta 4 – kompatibilno ili ne.

Zadatak

Koje promjene API-ja v1 su kompatibilne? a) dodano polje procijenjeno_vrijeme_min u odgovor narudžbe; b) polje ukupno sada je u eurima s decimalama (24.5) umjesto u centima; c) nova adresa GET /v1/restorani; d) polje kod u zahtjevu postaje obavezno; e) stanje NA_PUTU preimenovano u U_DOSTAVI.

Vježba za studenta 4 – kompatibilno ili ne. – rješenje

Rješenje (R)

Kompatibilne: a) i c). Nekompatibilne: b) (promjena tipa i značenja: stara aplikacija bi prikazala 0,24 €), d) (stari klijenti ne šalju kod, pa bi dobili grešku), e) (stari klijenti ne prepoznaju novo stanje). Za b, d i e treba verzija v2.

Vježba za studenta 5 – ponovni pokušaj.

Zadatak

Servis mapa ne odgovara. DeliveryApp čeka najviše 2 sekunde po pokušaju i ponavlja najviše tri puta, s pauzama 0,5 s, 1 s i 2 s između pokušaja. Koliko najduže kupac čeka dok ne vidi poruku o grešci? Da li to poštuje alternativni tok 3a (10 sekundi)?

Vježba za studenta 5 – ponovni pokušaj. – rješenje

Rješenje (R)

Četiri pokušaja (prvi i tri ponovna) po najviše 2 s = 8 s, plus pauze 0,5 + 1 + 2 = 3,5 s, ukupno 11,5 s. To je više od 10 sekundi, pa ne poštuje tok 3a; treba smanjiti broj pokušaja ili trajanje čekanja (npr. tri pokušaja po 2 s i pauze 0,5 s i 1 s daju 6 + 1,5 = 7,5 s).

Sažetak u pet rečenica

  1. API je ugovor po kojem jedan program traži uslugu od drugog, a priča o letjelici Mars Climate Orbiter iz 1999. pokazuje da sistem propada kad dva ispravna programa krše dogovor, makar samo u jedinici.
  2. HTTP zahtjev ima metodu, adresu, zaglavlja i tijelo, a odgovor statusni kod; REST API DeliveryApp ima pet adresa nastalih iz sekvencijalnog dijagrama i vraća 409 za nedozvoljen prelaz i 422 za kršenje pravila.
  3. Podaci putuju kao JSON, a svaki broj nosi jedinicu (centi, km, vrijeme u UTC), dok OpenAPI zapisuje ugovor prije koda, pa iz njega nastaju dokumentacija, kod klijenta i testovi.
  4. Nekompatibilne promjene traže novu verziju API-ja, a dijelovi razgovaraju sinhronim pozivom, webhookom ili događajima u redu poruka, zavisno od toga ko mora čekati.
  5. Vanjske sisteme pozivamo s vremenskim ograničenjem, ponovnim pokušajem s pauzom i idempotentnim ključem, preko HTTPS-a s tokenom i provjerom prava na svakom zahtjevu.

Pitanja za ponavljanje

  1. Šta se desilo letjelici Mars Climate Orbiter i kakve veze to ima s API-jem?
  2. Šta je API? Objasnite ga pomoću šaltera s jelovnikom.
  3. Od kojih dijelova se sastoje HTTP zahtjev i odgovor?
  4. Šta rade metode GET, POST, PATCH, PUT i DELETE?
  5. Navedite grupe statusnih kodova i šest konkretnih kodova sa značenjem.
  6. Šta je REST? Navedite adrese API-ja DeliveryApp v1.
  7. Šta je idempotentnost? Koje metode su idempotentne?
  8. Šta je JSON? Zašto svaki broj u JSON-u treba imati jedinicu?
  9. Šta je OpenAPI i šta znači pristup API-first?
  10. Koje promjene API-ja su kompatibilne, a koje ne? Kada se pravi nova verzija?
  11. Objasnite razliku između sinhronog poziva, webhooka i reda poruka i dajte primjer za svaki iz DeliveryApp.
  12. Koja tri alata koristimo kad vanjski sistem kasni ili ne odgovara?
  13. Kako idempotentni ključ sprečava duplu naplatu?
  14. Navedite četiri osnovna pravila sigurnosti API-ja.