A lecke végére el tudod dönteni, hogy egy API-változtatás visszafelé kompatibilis-e vagy törő, ismered a verziózás lehetőségeit, és meg tudod mondani, mit kell tartalmaznia egy használható API-dokumentációnak.
Miért kell kezelni az API változását?
Az API több kliens számára hosszú távú szerződés. A szerver azonban változik: új funkciók, átnevezések, javítások. A kliensek nem frissülnek ugyanabban a pillanatban: egy böngészős felület azonnal, egy mobilalkalmazás hetek vagy hónapok múlva, egy külső partner rendszere talán soha. Ha a szolgáltató egyik napról a másikra megváltoztatja a szerződést, a régi kliensek elromlanak, miközben a hálózat és a HTTP hibátlanul működik. A verziózás, a kompatibilitás és a dokumentáció teszi követhetővé és kezelhetővé a változást.
Egy mező átnevezése több kliensnél
A Kurzuspont API-ja eddig cim mezőt küldött. Az új szerverfejlesztés megnevezes-re nevezné át. Az új felület az új mezőt olvasná, a régi mobilalkalmazás viszont továbbra is cim-et vár. Kipróbálva, egy régi és egy újabb kliens ugyanazzal a három válasszal:
constregiKliens = v => "Kurzus: " + v.cim;
constujKliens = v => "Kurzus: " + (v.megnevezes ?? v.cim);
Az átnevezés elrontotta a régi klienst (undefined), a bővítés viszont nem. A harmadik megoldás átmenetileg a két mezőt együtt küldi, így mindkét kliens működik.
flowchart LR
R[Régi kliens: cim] --> A[API-válasz]
U[Új kliens: megnevezes] --> A
A --> D[Kompatibilitási döntés]
D --> M[Átmeneti együttélés vagy új verzió]
Kompatibilis és törő változás
Változás
Hatása a régi kliensre
Jellemzően
Új, opcionális válaszmező
A régi kliens figyelmen kívül hagyhatja
visszafelé kompatibilis
Új végpont
A régi kliens nem használja
kompatibilis
Kötelező mező eltávolítása
A kliens nem találja
törő
Mező átnevezése
Mint fent
törő
Mező típusának megváltoztatása (szám → szöveg)
Típushibát okozhat (lásd 5.2)
törő
Mező jelentésének megváltoztatása a név megtartásával
Csendben hibás működés
törő, különösen alattomos
Új kötelező kérésmező
A régi kliens nem küldi
törő
Az, hogy egy módosítás valóban kompatibilis-e, a tényleges szerződéstől és a kliensek viselkedésétől függ. A hibaválaszok (státuszkód, hibaformátum) is a szerződés részei: ha a kliens eddig egy adott státuszra és hibaformára számított, a változás ott is törheti a működést.
Verziózási lehetőségek
Az új verziót több módon lehet megkülönböztetni:
az útvonalban:/api/v2/kurzusok;
kérésfejlécben: például a kliens egy fejlécben vagy a médiatípusban jelzi a kért verziót;
a sémában: GraphQL esetén új mezők bevezetése és a régiek jelölése elavultként, verziószám nélkül.
Nincs egyetlen kötelező forma. A cél az, hogy a kliens tudja, melyik szerződést használja, és legyen átmenet, ha a régi verziót később kivezetik.
Mit tartalmazzon a dokumentáció?
Egy használható API-leírás megmondja:
mire való a szolgáltatás és milyen hozzáférés kell hozzá;
hol érhetők el a műveletek, milyen metódussal;
milyen bemenet kell, mely mezők kötelezők vagy opcionálisak;
milyen sikeres és hibás válasz várható (státuszkód és törzs);
mit jelentenek a mezők, milyen típusúak, mi lehet hiányzó vagy null;
hogyan változott a szerződés, mi van kivezetés alatt.
A példák segítenek, de nem helyettesítik a szabályok leírását: egy mintaválasz nem mondja meg, mi történik hiányzó adatnál vagy jogosultsági hibánál.
flowchart TD
S[API-szerződés] --> M[Műveletek és bemenetek]
S --> V[Válaszok és hibák]
S --> A[Adatmezők jelentése]
S --> K[Kompatibilitás és változások]
Az OpenAPI Specification nyelv- és gyártófüggetlen leírási forma HTTP API-khoz: a specifikáció szerint emberek és gépek a forráskód, a dokumentáció vagy a hálózati forgalom ismerete nélkül is megérthetik belőle, mit tud a szolgáltatás. A leírás gépi feldolgozásra is alkalmas (például kliens- vagy tesztkód generálására). Az oldal tanúsága szerint a specifikáció legfrissebb kiadása a 3.2.1. A jó dokumentáció azonban nem pusztán fájlformátum eredménye: a mezők pontos jelentése és a felhasználási feltételek is kellenek. GraphQL-nél a séma és a mezőleírások töltik be ugyanezt a szerepet.
Egy rövid OpenAPI-részlet a Kurzuspont GET /api/kurzusok/{id} műveletéhez (szemléltető, a szintaxist nem ellenőriztük validátorral):
A szolgáltató és a kliens együttműködését érdemes a régi és az új kliens szemszögéből is ellenőrizni: megkapja-e a régi kliens a szükséges mezőket? Érthetően reagál-e a hiányzó erőforrásra? Nem változott-e meg egy mező jelentése a név megtartása mellett? Ezek a kérdések a kompatibilitást konkrétan vizsgálják, nem csak egy verziószám meglétét.
Végigvezetett példa: a Kurzuspont v2-je
A Kurzuspont üzemeltetője át akarja nevezni a cim mezőt, és a ferohely mellé be akarja vezetni a szabadHely mezőt.
Lépés
Döntés
szabadHely hozzáadása
Opcionális bővítés, a régi kliensek figyelmen kívül hagyják: nem kell új verzió.
cim átnevezése megnevezes-re
Törő változás. Átmenetileg mindkét mező megy (fenti harmadik sor), a cim pedig „elavultként” szerepel a dokumentációban.
Kivezetés
A dokumentáció megadja a határidőt; a határidő után a cim megszűnik az új verzióban.
API-verziózás, kompatibilitás és dokumentáció
Célok
A lecke végére el tudod dönteni, hogy egy API-változtatás visszafelé kompatibilis-e vagy törő, ismered a verziózás lehetőségeit, és meg tudod mondani, mit kell tartalmaznia egy használható API-dokumentációnak.
Miért kell kezelni az API változását?
Az API több kliens számára hosszú távú szerződés. A szerver azonban változik: új funkciók, átnevezések, javítások. A kliensek nem frissülnek ugyanabban a pillanatban: egy böngészős felület azonnal, egy mobilalkalmazás hetek vagy hónapok múlva, egy külső partner rendszere talán soha. Ha a szolgáltató egyik napról a másikra megváltoztatja a szerződést, a régi kliensek elromlanak, miközben a hálózat és a HTTP hibátlanul működik. A verziózás, a kompatibilitás és a dokumentáció teszi követhetővé és kezelhetővé a változást.
Egy mező átnevezése több kliensnél
A Kurzuspont API-ja eddig
cimmezőt küldött. Az új szerverfejlesztésmegnevezes-re nevezné át. Az új felület az új mezőt olvasná, a régi mobilalkalmazás viszont továbbra iscim-et vár. Kipróbálva, egy régi és egy újabb kliens ugyanazzal a három válasszal:const regiKliens = v => "Kurzus: " + v.cim; const ujKliens = v => "Kurzus: " + (v.megnevezes ?? v.cim);{"id":"webprog","cim":"Webprogramozás 1."}(régi)Kurzus: Webprogramozás 1.Kurzus: Webprogramozás 1.{"id":"webprog","megnevezes":"Webprogramozás 1."}(átnevezett)Kurzus: undefinedKurzus: Webprogramozás 1.{"id":"webprog","cim":"...","megnevezes":"...","nyelv":"hu"}(bővített)Kurzus: Webprogramozás 1.Kurzus: Webprogramozás 1.Az átnevezés elrontotta a régi klienst (
undefined), a bővítés viszont nem. A harmadik megoldás átmenetileg a két mezőt együtt küldi, így mindkét kliens működik.flowchart LR R[Régi kliens: cim] --> A[API-válasz] U[Új kliens: megnevezes] --> A A --> D[Kompatibilitási döntés] D --> M[Átmeneti együttélés vagy új verzió]Kompatibilis és törő változás
Az, hogy egy módosítás valóban kompatibilis-e, a tényleges szerződéstől és a kliensek viselkedésétől függ. A hibaválaszok (státuszkód, hibaformátum) is a szerződés részei: ha a kliens eddig egy adott státuszra és hibaformára számított, a változás ott is törheti a működést.
Verziózási lehetőségek
Az új verziót több módon lehet megkülönböztetni:
/api/v2/kurzusok;Nincs egyetlen kötelező forma. A cél az, hogy a kliens tudja, melyik szerződést használja, és legyen átmenet, ha a régi verziót később kivezetik.
Mit tartalmazzon a dokumentáció?
Egy használható API-leírás megmondja:
null;A példák segítenek, de nem helyettesítik a szabályok leírását: egy mintaválasz nem mondja meg, mi történik hiányzó adatnál vagy jogosultsági hibánál.
flowchart TD S[API-szerződés] --> M[Műveletek és bemenetek] S --> V[Válaszok és hibák] S --> A[Adatmezők jelentése] S --> K[Kompatibilitás és változások]Az OpenAPI Specification nyelv- és gyártófüggetlen leírási forma HTTP API-khoz: a specifikáció szerint emberek és gépek a forráskód, a dokumentáció vagy a hálózati forgalom ismerete nélkül is megérthetik belőle, mit tud a szolgáltatás. A leírás gépi feldolgozásra is alkalmas (például kliens- vagy tesztkód generálására). Az oldal tanúsága szerint a specifikáció legfrissebb kiadása a 3.2.1. A jó dokumentáció azonban nem pusztán fájlformátum eredménye: a mezők pontos jelentése és a felhasználási feltételek is kellenek. GraphQL-nél a séma és a mezőleírások töltik be ugyanezt a szerepet.
Egy rövid OpenAPI-részlet a Kurzuspont
GET /api/kurzusok/{id}műveletéhez (szemléltető, a szintaxist nem ellenőriztük validátorral):paths: /api/kurzusok/{id}: get: summary: Egy kurzus lekérése parameters: - name: id in: path required: true schema: { type: string } responses: "200": { description: A kurzus } "404": { description: Nincs ilyen kurzus }A szerződés próbája
A szolgáltató és a kliens együttműködését érdemes a régi és az új kliens szemszögéből is ellenőrizni: megkapja-e a régi kliens a szükséges mezőket? Érthetően reagál-e a hiányzó erőforrásra? Nem változott-e meg egy mező jelentése a név megtartása mellett? Ezek a kérdések a kompatibilitást konkrétan vizsgálják, nem csak egy verziószám meglétét.
Végigvezetett példa: a Kurzuspont
v2-jeA Kurzuspont üzemeltetője át akarja nevezni a
cimmezőt, és aferohelymellé be akarja vezetni aszabadHelymezőt.szabadHelyhozzáadásacimátnevezésemegnevezes-recimpedig „elavultként” szerepel a dokumentációban.cimmegszűnik az új verzióban.Így a régi mobilalkalmazás frissítésére van idő, és senki nem látja egyik napról a másikra az
undefinedszöveget.Gyakori tévhitek
Röviden
Ellenőrző kérdések
Tanulási források