Poglavlje 10: Integracija i API
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.
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.
Literatura. Osnovna literatura predmeta:
- B. Popović, K. Kuk: Informacioni sistemi, Kriminalističko-policijski univerzitet, Beograd, 2017.
- J. S. Valacich, J. F. George: Modern Systems Analysis and Design, 9th ed., Pearson, 2020.
- L. Jelenković: Sustavi za rad u stvarnom vremenu – skripta, FER, Zagreb, 2015.
- D. Milićev: Programiranje u realnom vremenu – skripta, Beograd, 2002.
- V. Kovačević, M. Popović: Sistemska programska podrška u realnom vremenu 1, FTN, Novi Sad, 2013.
Riječi ovog poglavlja.
- 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).
- 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.
- 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
| Čas | Sadržaj | Na času |
|---|---|---|
| Teorija 1 | 10.1–10.3 API, HTTP, REST | Šalter s jelovnikom; pet adresa DeliveryApp |
| Teorija 2 | 10.4–10.6 JSON, jedinice, OpenAPI, verzije | Mars 1999: 4,45 puta; ugovor prije koda |
| Teorija 3 | 10.7–10.9 Webhook, događaji, vanjski servisi, sigurnost | Kako se kartica ne naplati dvaput |
| Praksa 1–3 | FastAPI server; HTTPie; /docs; OpenAPI | 201, 422, 409 i 24,50 € |
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.
- 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:
- metodu – šta želimo uraditi;
- adresu (URL) – nad čim, npr.
/v1/narudzbe/N-1001; - zaglavlja – dodatne informacije, npr. u kojem formatu šaljemo i ko smo (token za prijavu);
- tijelo – podaci, ako ih šaljemo (npr. stavke narudžbe).
Odgovor ima statusni kod, zaglavlja i tijelo.
HTTP metode
| Metoda | Šta radi | Primjer u DeliveryApp |
|---|---|---|
GET |
čita, ne mijenja ništa | pročitaj jelovnik restorana R-1 |
POST |
pravi nešto novo | napravi narudžbu |
PATCH |
mijenja dio postojećeg | promijeni stanje narudžbe u PRIHVAĆENA |
PUT |
zamjenjuje cijelo postojeće | zamijeni cijeli jelovnik |
DELETE |
briše | ukloni jelo s jelovnika |
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.
| Kod | Značenje | Kada ga DeliveryApp vraća |
|---|---|---|
| 200 OK | uspjeh | jelovnik je pročitan, cijena izračunata |
| 201 Created | napravljeno | nova narudžba N-1001 |
| 400 Bad Request | zahtjev je pokvaren | tijelo nije ispravan JSON |
| 401 Unauthorized | niste prijavljeni | nema tokena za prijavu |
| 403 Forbidden | prijavljeni ste, ali nemate pravo | kupac pokušava promijeniti stanje narudžbe |
| 404 Not Found | ne postoji | narudžba N-9999 |
| 409 Conflict | sukob sa stanjem | otkazivanje narudžbe u pripremi (PP-6) |
| 422 Unprocessable Content | podaci su čitljivi, ali krše pravilo | adresa 11 km (PP-3), iznos 4,50 € (PP-1) |
| 500 Internal Server Error | greška u našem kodu | izuzetak koji nismo predvidjeli |
| 503 Service Unavailable | server privremeno ne može | preopterećenje ili održavanje |
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.

Ukratko.
- 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:
| Metoda i adresa | Šta radi | Uspjeh | Greške |
|---|---|---|---|
GET /v1/jela?restoran=R-1 |
jela jednog restorana | 200 | – |
POST /v1/cijena |
izračunaj cijenu (ne čuva ništa) | 200 | 422 |
POST /v1/narudzbe |
napravi narudžbu u stanju NOVA | 201 | 404, 422 |
GET /v1/narudzbe/N-1001 |
pročitaj narudžbu | 200 | 404 |
PATCH /v1/narudzbe/N-1001/stanje |
promijeni stanje | 200 | 404, 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.
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.
- 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.
- Koju metodu koristimo za čitanje jelovnika? – GET.
- Koji statusni kod vraća server kad kupac naruči na 11 km? – 422, jer zahtjev krši pravilo PP-3.
- Zašto POST /v1/narudzbe nije idempotentan? – Jer svaki ponovljeni poziv pravi novu narudžbu.
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:
{
"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:
| Podatak | Opasnost | Dogovor DeliveryApp |
|---|---|---|
| novac | eur ili centi? decimalni zarez ili tačka? | cijeli broj centi, polje valuta |
| udaljenost | km ili milje? | km, u imenu polja |
| vrijeme | koja vremenska zona? 03/04 je mart ili april? | ISO 8601 u UTC: 2026-10-02T10:10:00Z |
| tekst | kodiranje slova č, ć, ž | UTF-8 |
| stanje | „Prihvacena”, „prihvaćena”, „ACCEPTED”? | tačno jedna od sedam vrijednosti iz poglavlja 7 |
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.
- 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: 1YAML je format sličan JSON-u, ali bez zagrada: uvlačenje redova pokazuje šta je unutar čega. Ovaj opis čitaju i ljudi i programi:
- 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.
- 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
ukupnouukupno_centi, to je sitnica.” Za server jeste. Za svaku staru aplikaciju koja traži poljeukupno, 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.
- 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.
- 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.
- Šta automatski nastaje iz OpenAPI opisa? – Dokumentacija, kod klijenta i testovi ugovora.
- Je li dodavanje novog polja u odgovor kompatibilna promjena? – Da; stari klijent ga ignoriše.
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:
- 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.
- 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
POSTna našu adresu/v1/placanja/potvrda. Ne moramo ga pitati svakih pet sekundi „je li plaćeno?”. - 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.
| Strelica u DeliveryApp | Način | Zašto |
|---|---|---|
| aplikacija → server: cijena | sinhrono | kupac mora vidjeti cijenu odmah |
| server → servis mapa: udaljenost | sinhrono | bez udaljenosti nema cijene |
| sistem plaćanja → server: potvrda | webhook | banka odgovara za nekoliko sekundi; ne čekamo |
| server → servis obavještenja: „spremna” | događaj u redu | obavještenje ne smije usporiti restoran |
| server → izvještaji: „isporučena” | događaj u redu | izvještaj se računa kasnije, svojim tempom |

Ukratko.
- 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.
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.
- 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:
- 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.
- 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. - 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.
- 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.
- 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.
- Kojim načinom sistem plaćanja javlja da je plaćanje odobreno? – Webhookom: sam pošalje zahtjev na našu adresu.
- Koliko ukupno čekamo kod tri ponovna pokušaja s pauzama 1, 2 i 4 s? – 7 sekundi.
- Čemu služi idempotentni ključ kod plaćanja? – Da ponovljeni zahtjev ne naplati karticu još jednom.
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
- U terminalu, u folderu
kod/:
pip install fastapi uvicorn httpie
- Kopirajte
api.pyiopenapi.yamlizprimjeri/deliveryapp/(uzdeliveryapp.pykoji već imate). - Pokrenite server:
uvicorn api:app --reload
- Otvorite u pregledniku
http://127.0.0.1:8000/docs. FastAPI je sam napravio dokumentaciju iz koda, po standardu OpenAPI. OtvoritePOST /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
- Napravite narudžbu: isti zahtjev kao u koraku 2, ali
POST :8000/v1/narudzbe. Očekivano: 201 Created i"broj": "N-1001","stanje": "NOVA". - 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.
- Pročitajte narudžbu (
http GET :8000/v1/narudzbe/N-1001) i pogledajte poljeistorija.
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žba za studenta 1 – metoda i kod.
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.
Rješenje. 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.
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.
Rješenje. 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.
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.
Rješenje. 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.
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.
Rješenje. 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.
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)?
Rješenje. Č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
- 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.
- 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.
- 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.
- 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.
- 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.