Vezérlőpult
2. A REST API · Backend elméleti alapok

Backend elméleti alapok · 2. tananyag

A REST API

Amikor egy mobilalkalmazás betölti a termékeket, amikor egy weboldal elküld egy űrlapot, amikor egy időjárás-widget lekéri a hőmérsékletet — szinte mindig ugyanaz történik: egy program HTTP-kérést küld egy másik program API-jának, és JSON-választ kap. Ez a világ legelterjedtebb backend-felülete, és ezt hívjuk REST API-nak.

3 tanóraElmélet + gyakorlatA következő hetek szabálykönyve

A fejezet végén tudni fogod

1Mi az a HTTP?

A HTTP (HyperText Transfer Protocol) az a „nyelv”, amelyen a kliens és a szerver beszél. Két alapszabálya van:

JÓ TUDNI

A https:// ugyanaz a HTTP, csak TLS-sel (Transport Layer Security) titkosítva. Az adat így útközben nem olvasható és nem módosítható. Élesben ma már mindig HTTPS-t használunk; fejlesztés közben a localhost HTTP-je is elfogadható.

A HTTP verziói: HTTP/1.1 (a legelterjedtebb, szöveges), HTTP/2 (bináris, párhuzamos), HTTP/3 (QUIC protokollon). A mi szempontunkból mindegyik ugyanúgy néz ki: kérés, válasz, metódus, státuszkód, fejlécek, törzs.

2Az URL felépítése

https:// api.webshop.hu :443 /api/v1/products/42 ?fields=name,price #reszletek séma a protokoll: http vagy https gazdagép (host) melyik gépet keressük — a DNS oldja fel IP-címre port melyik programot a gépen — elhagyható, ha 80 vagy 443 útvonal (path) melyik erőforrást kérjük — ez a REST szíve query string szűrés, rendezés, lapozás — kulcs=érték párokban töredék az oldalon belüli hely — a szerverhez el sem jut Jelszó, token, személyes adat SOHA nem kerül az URL-be. Megmarad a böngésző előzményeiben, a szerver naplóiban és a hivatkozó fejlécekben.
1. ábra — Az URL hat része. A backend számára az útvonal és a query a fontos.
RészSzerepMegjegyzés
Sémahttp vagy httpsA protokoll
HostMelyik gépet keressükA DNS oldja fel IP-címre
PortMelyik programot a gépenElhagyható, ha alapértelmezett (80 / 443)
PathMelyik erőforrást kérjükEz a REST szíve
QuerySzűrés, rendezés, lapozás?kulcs=érték&kulcs2=érték2
FragmentAz oldalon belüli helyA szerverhez el sem jut!
FIGYELEM

A query stringben lévő adat megjelenik a böngésző előzményeiben, a szerver naplóiban és a hivatkozó fejlécekben. Jelszót, tokent, személyes adatot soha ne tegyél az URL-be — annak a kérés törzsében vagy fejlécében a helye.

3A kérés és a válasz anatómiája

Mindkettő négy részből áll: kezdősor · fejlécek · üres sor · törzs.

HTTP-KÉRÉS POST /api/products HTTP/1.1 kezdősor: METÓDUS · ÚTVONAL · VERZIÓ Host: api.webshop.hu Content-Type: application/json Authorization: Bearer eyJhbGci… fejlécek (headers) — metaadat a kérésről ÜRES SOR — ez választja el a törzstől { "name": "Billentyűzet", "price": 34990 } törzs (body) HTTP-VÁLASZ HTTP/1.1 201 Created kezdősor: VERZIÓ · STÁTUSZKÓD · SZÖVEG Content-Type: application/json Location: /api/products/58 Content-Length: 96 fejlécek — metaadat a válaszról ÜRES SOR { "id": 58, "name": "Billentyűzet" } törzs (body)
2. ábra — Ugyanaz a négy rész mindkét irányban. A törzs nem kötelező (a GET-nek például nincs).

Gyakori kérés-fejlécek

FejlécMire valóPélda
Content-TypeMilyen formátumú a küldött törzsapplication/json
AcceptMilyen formátumú választ várunkapplication/json
AuthorizationHitelesítő adatBearer <token>
User-AgentMilyen program küldiMozilla/5.0 …
CookieA böngésző sütijeisession=abc123
A KETTŐ NEM UGYANAZ

A Content-Type arról szól, amit küldesz; az Accept arról, amit kapni szeretnél. Ezt kezdők gyakran összekeverik.

4HTTP-metódusok

A metódus azt mondja meg, mit akarunk tenni az erőforrással. Ugyanaz az URL egészen mást jelent attól függően, melyik metódussal hívjuk meg — nézzük végig őket egyesével.

GET — kérd le!

A leggyakoribb metódus: adatot kérünk, de nem változtatunk semmit. Ez az egyetlen, amit a böngésző címsorába beírva is ki tudsz próbálni, és ezt használja a böngésző minden képhez, CSS-fájlhoz, oldalhoz. Nincs törzse: amit közölni akarsz vele (szűrés, lapozás), az az URL query részébe kerül. Mivel nem változtat, a válasza nyugodtan gyorsítótárazható.

POST — hozz létre újat!

Új erőforrás létrehozására való: új termék, új rendelés, új felhasználó. Az adatot a kérés törzsében küldjük, JSON-ban. A szerver dönti el, milyen azonosítót kap az új elem — ezért a válaszban kapjuk vissza. Ha kétszer küldöd el, két dolog jön létre: ez a metódus nem ismételhető büntetlenül. (Ezen kívül a POST a „gyűjtőhely” minden olyan műveletnek, ami nem fér bele a CRUD-ba — például a bejelentkezés.)

PUT — cseréld le az egészet!

Egy létező erőforrás teljes felülírása. Fontos: a PUT-nál az erőforrás minden mezőjét el kell küldeni, mert amit kihagysz, az elveszik — a szerver a beküldött állapotra cseréli a régit. Ha ötször küldöd el ugyanazt, ötször ugyanaz lesz az eredmény, ezért idempotens.

PATCH — módosíts egy részletet!

Akkor használjuk, ha csak néhány mezőt akarunk megváltoztatni. Ha egy termék árát kell átírni, PATCH-csel elég ennyit küldeni: { "price": 29990 } — a név, a leírás és a kategória érintetlen marad. PUT-tal ugyanezért az egész terméket újra be kellene küldeni.

PUT VAGY PATCH? — a szerkesztő űrlap példája

A tanuló a webshop admin felületén átírja egy termék árát:

PUT /products/42 → { "name": "Billentyűzet", "price": 29990, "categoryId": 3, "description": "…" }
Minden mezőt küldeni kell. Ha a description lemarad, a szerver törli.

PATCH /products/42 → { "price": 29990 }
Csak a változó mező megy át. A többi marad, ahogy volt.

DELETE — töröld!

Az erőforrás törlése. Általában nincs törzse (minden információ benne van az URL-ben), és sikeres törlés után jellemzően nincs mit visszaadni. Idempotens: ha másodszor is elküldöd, a termék ugyanúgy nem lesz meg — az állapot tehát ugyanaz marad, még ha a második kérés 404-et is kap.

HEAD — csak a fejléceket kérem!

Pontosan ugyanaz, mint a GET, de a szerver csak a fejléceket küldi vissza, a törzset nem. Arra jó, hogy valamit megtudj az erőforrásról anélkül, hogy letöltenéd: létezik-e egyáltalán, mekkora (Content-Length), mikor változott utoljára. Például egy letöltőprogram ezzel nézi meg egy 2 GB-os fájl méretét, mielőtt nekikezdene.

OPTIONS — mit tudsz, végpont?

Azt kérdezi meg, milyen metódusokat fogad el az adott útvonal; a válasz egy Allow fejlécben sorolja fel őket. A gyakorlatban ritkán írod le kézzel — viszont a böngésző magától küldi az ún. előkérésekben (preflight), amikor egy oldal más eredetű API-t hív. Ha a hálózati fülön furcsa OPTIONS-kéréseket látsz a saját kérésed előtt, az a CORS működése.

Összefoglaló táblázat

MetódusJelentésCRUDVan törzse?Biztonságos?Idempotens?
GETLekérésReadNincs✅✅
POSTÚj létrehozásaCreateVan❌❌
PUTTeljes lecserélésUpdateVan❌✅
PATCHRészleges módosításUpdateVan❌❌*
DELETETörlésDeleteÁltalában nincs❌✅
HEADMint a GET, de csak fejlécek—Nincs✅✅
OPTIONSMit tud ez a végpont?—Nincs✅✅

* A PATCH lehet idempotens, ha jól tervezzük, de a szabvány nem garantálja.

Két fontos fogalom

Biztonságos (safe): a kérés nem változtat a szerver állapotán. A GET csak olvas.

VESZÉLY

Klasszikus kezdő hiba: GET /products/42/delete. A böngésző, a keresőrobot vagy egy gyorsítótár bármikor „csak úgy” meglátogathat egy GET-címet — és ezzel véletlenül törölhet. Törlésre mindig DELETE metódus való.

Idempotens: ha ugyanazt a kérést többször elküldöd, az eredmény ugyanaz, mintha egyszer küldted volna.

KérésEgyszerÖtszörIdempotens?
GET /products/42Visszaadja a terméketVisszaadja a terméket✅
PUT /products/42 {ar: 1000}Az ár 1000 leszAz ár 1000 marad✅
DELETE /products/42TörliMár nincs mit törölni — az állapot ugyanaz✅
POST /orders1 rendelés jön létre5 rendelés jön létre❌
EZÉRT KÉRDEZ RÁ A BÖNGÉSZŐ

Amikor újratöltéskor felugrik, hogy „biztosan újraküldi az űrlapot?”, az pontosan azért van, mert a POST nem idempotens, és kétszer is végrehajtódhat. Ez a valóságban is probléma (dupla rendelés), ezért a fizetéseknél idempotencia-kulcsot szoktak használni.

5Státuszkódok

A státuszkód három számjegy, és az első számjegy adja a kategóriát.

Státuszkód 3 számjegy 1xx Információ — ritkán találkozol vele 2xx Sikeres 200 OK · 201 Created · 204 No Content 3xx Átirányítás 301 Moved · 304 Not Modified 4xx A KLIENS hibája 400 · 401 · 403 · 404 · 409 · 422 · 429 5xx A SZERVER hibája 500 · 502 · 503 · 504 MEGJEGYZÉSNEK 4xx = „te rontottad el” 5xx = „mi rontottuk el”
3. ábra — Az első számjegy már önmagában megmondja, kinél keresd a hibát.

A gyakorlatban használt kódok

KódNévMikor használjuk?
200OKSikeres GET, PUT, PATCH — van válasz-törzs
201CreatedSikeres POST: új erőforrás jött létre. Adjunk Location fejlécet is!
204No ContentSikeres művelet, de nincs mit visszaadni (tipikusan DELETE)
304Not ModifiedA gyorsítótárban lévő változat még jó
400Bad RequestHibás, értelmezhetetlen kérés (pl. rossz JSON)
401UnauthorizedNem vagy bejelentkezve (hiányzik vagy lejárt a token)
403ForbiddenBe vagy jelentkezve, de nincs jogosultságod
404Not FoundNincs ilyen erőforrás
405Method Not AllowedLétező útvonal, de ezzel a metódussal nem használható
409ConflictÜtközés (pl. már létezik ilyen e-mail cím)
415Unsupported Media TypeNem támogatott Content-Type
422Unprocessable ContentA kérés formailag jó, de tartalmilag hibás (validációs hiba)
429Too Many RequestsTúl sok kérés rövid idő alatt (rate limiting)
500Internal Server ErrorKezeletlen hiba a szerveren
502 503Bad Gateway / Service UnavailableNem érhető el vagy nem válaszol a mögöttes szolgáltatás
FIGYELEM — a 401 és a 403 különbsége

401 Unauthorized: „Nem tudom, ki vagy.” → jelentkezz be.
403 Forbidden: „Tudom, ki vagy, de ezt nem teheted.” → nincs jogod hozzá.
A név megtévesztő: a 401 valójában hitelesítési, nem jogosultsági hiba.

JÓ TUDNI — 400 vagy 422?

Bevett gyakorlat: a kérés formája hibás (érvénytelen JSON) → 400; a kérés jó formájú, de az adat nem érvényes (negatív ár, hiányzó kötelező mező) → 422. Sok API mindkét esetben 400-at ad — a lényeg, hogy következetes légy.

Melyik státuszkódot küldöd?

Ez a fejezet legfontosabb gyakorlati készsége. Nyolc helyzet — válaszd ki a helyes kódot!

1 / 8 helyzetHelyes: 0
…

6JSON — az adatcsere formátuma

A JSON (JavaScript Object Notation) egy szöveges adatformátum. A JavaScript objektum-szintaxisából származik, de ma már minden programozási nyelv kezeli.

{
  "id": 42,
  "name": "Mechanikus billentyűzet",
  "price": 34990,
  "inStock": true,
  "discount": null,
  "tags": ["billentyűzet", "gaming"],
  "category": {
    "id": 3,
    "name": "Perifériák"
  }
}

A JSON hat adattípusa

TípusPélda
szöveg (string)"Anna" — csak kettős idézőjel!
szám (number)42, 3.14, -7 (nincs külön egész és tört)
logikai (boolean)true, false
nullnull
tömb (array)[1, 2, 3], ["a", "b"]
objektum (object){ "kulcs": "érték" }

Amit a JSON NEM tud

Hiba❌ Rossz✅ Jó
Aposztróf{ 'nev': 'Anna' }{ "nev": "Anna" }
Idézőjel nélküli kulcs{ nev: "Anna" }{ "nev": "Anna" }
Záró vessző{ "a": 1, }{ "a": 1 }
Komment// megjegyzés(nincs JSON-ban komment)
Dátum típus2026-03-15"2026-03-15T10:30:00Z"
Függvény, undefined{ "f": () => 1 }(nem létezik JSON-ban)
DÁTUMOK

Mindig ISO 8601 formátumban, UTC-ben küldjük: "2026-03-15T10:30:00.000Z". Így nincs félreértés a 03/15 és a 15/03 között.

JSON ↔ JavaScript

// Objektum → JSON-szöveg
const szoveg = JSON.stringify({ nev: "Anna", kor: 17 });
// '{"nev":"Anna","kor":17}'

// JSON-szöveg → objektum
const objektum = JSON.parse('{"nev":"Anna","kor":17}');
// { nev: 'Anna', kor: 17 }

Fontos: a hálózaton szöveg utazik. A JSON.parse és a JSON.stringify a fordítók a szöveg és az objektum között. (Express-szel ezt később nagyrészt automatikusan megkapjuk.)

JSON-ellenőrző

Írd át a szöveget, és nézd meg, mit mond rá a JSON.parse — ugyanaz az elemző fut, mint a szerveren.

Nyomd meg az Ellenőrzés gombot…

Miért nem XML?

A JSON előtt az XML (eXtensible Markup Language) volt az adatcsere szabványa — a 2000-es évek web-szolgáltatásai szinte kivétel nélkül ezt használták, és sok vállalati rendszer ma is így beszél. Az XML felépítése ismerős lesz: ugyanolyan elemekből áll, mint a HTML — nyitó és záró tagekből —, csak a tagek nevét te találod ki.

Nézzük meg ugyanazt a terméket mindkét formátumban:

Ugyanaz JSON-ban

{
  "id": 42,
  "name": "Mechanikus billentyűzet",
  "price": 34990,
  "inStock": true,
  "tags": ["billentyűzet", "gaming"],
  "category": { "id": 3, "name": "Perifériák" }
}

Ugyanaz XML-ben

<?xml version="1.0" encoding="UTF-8"?>
<product>
  <id>42</id>
  <name>Mechanikus billentyűzet</name>
  <price>34990</price>
  <inStock>true</inStock>
  <tags>
    <tag>billentyűzet</tag>
    <tag>gaming</tag>
  </tags>
  <category>
    <id>3</id>
    <name>Perifériák</name>
  </category>
</product>

A tartalom pontosan ugyanannyi, a JSON mégis nagyjából feleakkora. Az XML minden adatdarabot kétszer nevez meg (nyitó és záró tag), és a legtöbb API-nál ez a többlet semmit nem ad hozzá.

Négy érdemi különbség

SzempontJSONXML
MéretKisebbNagyobb (nyitó + záró tagek)
AdattípusokBeépített (szám, logikai, null, tömb)Nincs — minden szöveg
ListaTermészetes ([…])Megegyezés kérdése
Feldolgozás JavaScriptbenJSON.parse — beépítettKülön elemző, DOM-bejárás
Séma, érvényesítésKülön eszközzel (JSON Schema, Zod)Beépített, erős (XSD)
Megjegyzés a fájlbanNem lehetLehet
Elterjedtség web-API-kbanUralkodóRégebbi, vállalati rendszerek (SOAP)
AKKOR AZ XML ROSSZ?

Nem — csak másra jó. Ahol a dokumentum szerkezete a lényeg (szövegek jelölése, kiadványok, konfigurációs szabványok), ott az XML erősebb: van hozzá szigorú séma (XSD), névtér-kezelés és lekérdezőnyelv (XPath). Programok közti adatcserére viszont a JSON kisebb, egyszerűbb és típusosabb — ezért lett ez a web-API-k formátuma.

7Mi az API, és mi a REST?

Az API (Application Programming Interface) két program közötti „szerződés”: leírja, hogyan lehet egy szolgáltatás funkcióit használni.

HASONLAT

Az étterem étlapja. Nem kell tudnod, hogyan működik a konyha; elég, hogy van egy lista arról, mit rendelhetsz és mit kapsz érte. Az étlap az API, a konyha az implementáció.

A web-API olyan API, amelyet HTTP-n keresztül lehet elérni. Ilyen a REST is.

A REST

A REST (REpresentational State Transfer) egy architekturális stílus, amelyet Roy Fielding írt le 2000-ben, a doktori disszertációjában. Fielding egyike volt a HTTP/1.1 szabvány szerzőinek — a REST tulajdonképpen annak összefoglalása, hogyan van kitalálva a web, és hogyan érdemes ezt az API-knál is követni.

FONTOS

A REST nem szabvány, nem protokoll és nem könyvtár. Nem lehet „telepíteni”. Ez egy elvrendszer, ajánlások összessége. Ezért van, hogy két REST API sem néz ki teljesen egyformán — és ezért vitatkoznak a fejlesztők azon, „mennyire RESTes” egy API.

A központi gondolat: minden dolog erőforrás (resource), amelynek van egy címe (URI), és amelyet egységes műveletekkel (HTTP-metódusokkal) kezelünk.

        NEM így gondolkodunk:                      Hanem így:
  "hívjuk meg a termékTörlés()-t"     →     "töröljük a /products/42 erőforrást"
        (műveletközpontú)                      (erőforrás-központú)

8A REST hat alapelve

Fielding hat megszorítást (constraint) fogalmazott meg. Ezek együtt adják a REST-et.

1) Kliens–szerver szétválasztás

A felhasználói felület és az adattárolás külön fejlődik. Ugyanazt az API-t használhatja weboldal, mobilapp és külső partner is.

2) Állapotmentesség (stateless)

A szerver nem tárol munkamenet-állapotot a kérések között. Minden kérésnek magában kell hordoznia mindent, ami a feldolgozásához kell — így a hitelesítő adatot is.

MUNKAMENET A SZERVER MEMÓRIÁJÁBAN kliens terhelés- elosztó 1. szerver ismeri a munkamenetet 2. szerver NEM ismeri → 401 A második kérés kiesik, ha másik szerverre irányítják. ÁLLAPOTMENTES — A TOKEN A KÉRÉSBEN UTAZIK kliens +token terhelés- elosztó 1. szerver a tokenből tudja, ki vagy 2. szerver a tokenből tudja, ki vagy Mindegy, melyik szerver kapja meg — és az újraindítás sem zavar. Így skálázható.
4. ábra — Ezért fogunk a webshopnál JWT-t használni: a token magában hordozza, ki a felhasználó.
JÓ TUDNI

Állapotmentes ≠ adatmentes! Az adatok természetesen az adatbázisban maradnak. Csak a munkamenet nem él a szerver memóriájában.

3) Gyorsítótárazhatóság (cacheable)

A válaszok megjelölhetők, hogy eltárolhatók-e és meddig (Cache-Control, ETag). Így a kliens vagy egy köztes réteg (CDN — Content Delivery Network) újra felhasználhatja őket: kevesebb hálózat, gyorsabb alkalmazás.

4) Egységes felület (uniform interface)

Ez a REST védjegye. Négy összetevője:

5) Rétegzett rendszer (layered system)

A kliens nem tudja (és nem is kell tudnia), hogy közvetlenül a szerverrel beszél-e, vagy egy köztes réteggel (proxy, terheléselosztó, gyorsítótár). Bármikor beszúrható közéjük réteg.

6) Kód igény szerint (code on demand) — opcionális

A szerver futtatható kódot is küldhet a kliensnek (például JavaScriptet). Ez az egyetlen nem kötelező alapelv, és a gyakorlatban ritkán számít az API-knál.

JÓ TUDNI — HATEOAS

Hypermedia As The Engine Of Application State. Azt jelenti, hogy a válasz tartalmazza, „innen hova mehetsz tovább”:

{ "id": 42, "name": "Billentyűzet",
  "_links": { "self": "/api/products/42", "category": "/api/categories/3" } }

Elméletileg ez a „teljes” REST része, a gyakorlatban a legtöbb API kihagyja, mert bonyolítja a fejlesztést. Mi sem fogjuk használni, de tudnod kell, hogy létezik.

Richardson érettségi modell

Hasznos skála arra, „mennyire RESTes” egy API:

0. szint „A mocsár” 1. szint Erőforrások 2. szint HTTP-igék + kódok ITT VAGYUNK a valódi API-k ~95%-a 3. szint HATEOAS egy URL, minden POST külön URL-ek, de POST helyes metódus és státuszkód a válasz linkeket is ad Egyre „RESTesebb” →
5. ábra — A 3. szint (HATEOAS) elméletileg a cél, a gyakorlatban a 2. szint az iparági szokás.

9Erőforrás-orientált URL-tervezés

Ez a rész a fejezet legfontosabb gyakorlati tudása.

Alapszabályok

Szabály❌ Rossz✅ Jó
Főnév, ne ige — az igét a metódus adja/getProducts, /createProductGET /products, POST /products
Többes szám a gyűjteményeknek/product/42/products/42
Kisbetű, kötőjel/OrderItems, /order_items/order-items
Hierarchia a kapcsolatokhoz/getOrdersOfUser?id=5/users/5/orders
Ne legyen kiterjesztés/products.json/products (+ Accept fejléc)
Szűrés query stringben/products/cheap/products?maxPrice=5000
Ne legyen záró perjel/products//products

A CRUD-műveletek megfeleltetése

/api/products GYŰJTEMÉNY /api/products/42 EGY ELEM GET összes termék listája 200 · tömb egy termék adatai 200 · objektum · 404, ha nincs POST új termék létrehozása 201 + Location fejléc nem használjuk · 405 PUT nem használjuk · 405 teljes felülírás 200 · minden mezőt küldeni kell PATCH nem használjuk · 405 részleges módosítás 200 · csak a változó mezők DELETE az egész gyűjtemény törlése — soha a termék törlése 204 · nincs válasz-törzs
6. ábra — Ugyanaz az öt metódus mást jelent a gyűjteményen és egyetlen elemen.
CélMetódus + útvonalSiker
Összes termék listájaGET /api/products200
Egy termék lekéréseGET /api/products/42200
Új termék létrehozásaPOST /api/products201 + Location
Termék teljes felülírásaPUT /api/products/42200
Termék részleges módosításaPATCH /api/products/42200
Termék törléseDELETE /api/products/42204
Egy termék értékeléseiGET /api/products/42/reviews200
Új értékelés a termékhezPOST /api/products/42/reviews201

Szűrés, rendezés, lapozás, keresés

Ezek nem külön végpontok, hanem query paraméterek ugyanazon a gyűjteményen:

GET /api/products?categoryId=3              // szűrés
GET /api/products?minPrice=1000&maxPrice=5000
GET /api/products?sort=price&order=asc      // rendezés
GET /api/products?page=2&limit=20           // lapozás
GET /api/products?q=billentyuzet            // keresés
GET /api/products?fields=id,name,price      // mezőválasztás

Lapozásnál a válasz általában metaadatot is tartalmaz:

{
  "data": [ { "id": 21, "name": "…" }, { "id": 22, "name": "…" } ],
  "meta": { "page": 2, "limit": 20, "total": 137, "totalPages": 7 }
}

Építsd meg a kérést!

Válaszd ki a metódust, az útvonalat és a paramétereket a feladathoz — aztán nézd meg, mit szólna hozzá a szerver.

1 / 4 feladatHelyes: 0
…

Amikor a művelet nem fér bele a CRUD-ba

Nem minden művelet „létrehozás/olvasás/módosítás/törlés”. Mit kezdjünk a bejelentkezéssel vagy egy rendelés lemondásával? Két bevett megoldás:

TIPP

A második megoldás nem „tiszta” REST, de elterjedt és elfogadott. A jó API a kiszámíthatóságot szolgálja, nem a szabálykövetés kedvéért létezik.

Verziózás

Ha az API úgy változik, hogy a régi kliensek eltörnek, verziózni kell:

MódPéldaMegjegyzés
URL-ben/api/v1/productsA legelterjedtebb, jól látható — mi ezt használjuk
FejlécbenAccept: application/vnd.shop.v1+json„Tisztább”, de nehezebben tesztelhető
Query-ben/api/products?version=1Ritkább

10Kérés–válasz példák a webshopból

Termékek listázása

GET /api/v1/products?categoryId=3&limit=2 HTTP/1.1
Host: api.webshop.hu
Accept: application/json
HTTP/1.1 200 OK
Content-Type: application/json

{
  "data": [
    { "id": 42, "name": "Mechanikus billentyűzet", "price": 34990, "inStock": true },
    { "id": 43, "name": "Vezeték nélküli egér",   "price": 12990, "inStock": false }
  ],
  "meta": { "page": 1, "limit": 2, "total": 17 }
}

Új termék létrehozása (adminként)

POST /api/v1/products HTTP/1.1
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

{ "name": "Gamer fejhallgató", "price": 24990, "categoryId": 3 }
HTTP/1.1 201 Created
Location: /api/v1/products/58
Content-Type: application/json

{ "id": 58, "name": "Gamer fejhallgató", "price": 24990, "categoryId": 3,
  "createdAt": "2026-03-15T10:30:00.000Z" }

Hibás adat — validációs hiba

POST /api/v1/products HTTP/1.1
Content-Type: application/json

{ "name": "", "price": -500 }
HTTP/1.1 422 Unprocessable Content
Content-Type: application/json

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "A megadott adatok érvénytelenek.",
    "details": [
      { "field": "name",  "message": "A név megadása kötelező." },
      { "field": "price", "message": "Az ár nem lehet negatív." }
    ]
  }
}

Hiányzó jogosultság

DELETE /api/v1/products/42 HTTP/1.1
Authorization: Bearer <egy sima felhasználó tokenje>
HTTP/1.1 403 Forbidden
Content-Type: application/json

{ "error": { "code": "FORBIDDEN",
    "message": "Ehhez a művelethez adminisztrátori jog szükséges." } }
EGYSÉGES HIBAFORMÁTUM

Válassz egy hibaszerkezetet, és az egész API-ban ugyanazt használd. A kliensfejlesztő így egyszer írja meg a hibakezelést, és minden végpontnál működni fog.

Van rá szabvány is: RFC 9457 — Problem Details

Ha nem akarsz saját hibaszerkezetet kitalálni, használhatod az RFC 9457 szabványt („Problem Details for HTTP APIs”). Ennél a válasz Content-Type fejléce nem application/json, hanem application/problem+json, a törzs pedig előre megbeszélt mezőneveket használ:

HTTP/1.1 422 Unprocessable Content
Content-Type: application/problem+json

{
  "type":     "https://api.webshop.hu/hibak/ervenytelen-adat",
  "title":    "A megadott adatok érvénytelenek.",
  "status":   422,
  "detail":   "Az ár nem lehet negatív, a név pedig kötelező.",
  "instance": "/api/v1/products",

  // a szabvány engedi, hogy saját mezőkkel bővítsd:
  "errors": [
    { "field": "name",  "message": "A név megadása kötelező." },
    { "field": "price", "message": "Az ár nem lehet negatív." }
  ]
}
MezőMit tartalmaz?
typeA hibatípus azonosítója — jellemzően egy URL, ahol el is olvasható a magyarázata
titleRövid, ember által olvasható cím. Ugyanahhoz a type-hoz mindig ugyanaz
statusA HTTP-státuszkód megismételve a törzsben
detailEhhez a konkrét esethez tartozó magyarázat
instanceMelyik kérésnél történt (útvonal vagy hibaazonosító)

Miért jó ez? Mert a mezőnevek nem a te fejedből származnak: egy külső fejlesztő, aki még soha nem látta az API-dat, a Content-Type-ból azonnal tudja, mire számítson. Számos keretrendszerhez létezik hozzá kész kliensoldali kezelő is.

MI HOGYAN CSINÁLJUK?

A webshop-projektben a fentebb bemutatott, egyszerűbb saját { "error": { … } } szerkezetet fogjuk használni — kevesebb ceremónia, és tanulni is könnyebb rajta. Azért ismerd az RFC 9457-et, mert éles projektekben és publikus API-kban gyakran ezzel fogsz találkozni.

VESZÉLY

A hibaüzenet soha ne szivárogtasson belső információt: SQL-lekérdezést, fájlútvonalat, stack trace-t, könyvtárneveket. Ezek a támadónak adnak segítséget. A részletes hiba a naplóba való, a kliens csak általános üzenetet kapjon.

11Előnyök és hátrányok

A REST előnyei

ElőnyMagyarázat
Egyszerű és ismerősA HTTP-re épül, amit minden fejlesztő és minden eszköz ismer
PlatformfüggetlenA szerver Node.js, a kliens Android — nem számít
Jól skálázhatóAz állapotmentesség miatt tetszőleges számú szerver mögé tehető
GyorsítótárazhatóA GET-válaszok cache-elhetők (böngésző, CDN, proxy)
KliensfüggetlenUgyanazt az API-t használja a web, a mobil és a partnerrendszer
Könnyen tesztelhetőBöngészőből, curl-lel, REST Clienttel azonnal kipróbálható
Kiváló eszköztámogatásOpenAPI-dokumentáció, generátorok, tesztelők
Fokozatosan fejleszthetőÚj végpontok adhatók hozzá a régiek törése nélkül

A REST hátrányai

HátrányMagyarázatEnyhítés
Túl sok adat (over-fetching)A /users/5 mindent visszaad, pedig csak a név kellett?fields= paraméter
Túl kevés adat (under-fetching, N+1 kérés)A lista után minden elemhez külön kérés kellBeágyazás (?include=category) vagy GraphQL
Nincs szigorú szerződésA REST nem írja elő a válasz szerkezetétOpenAPI-leírás, TypeScript-típusok
Merev erőforrás-modellBonyolult műveletek nehezen erőltethetők CRUD-baMűvelet-alerőforrások
Verziózási teherA változás könnyen töri a régi klienseketVerziózás, visszafelé kompatibilitás
Szöveges és terjengősA JSON nagyobb, mint egy bináris formátumTömörítés (gzip, brotli), gRPC belső hívásokra
Nincs valós idejű támogatásA szerver nem tud magától szólniWebSocket vagy SSE külön
MI AZ AZ N+1 KÉRÉS?

Lekéred a 20 terméket (1 kérés), majd mindegyikhez külön lekéred a kategóriáját (20 kérés) — összesen 21 hálózati kör. Ugyanez a probléma az adatbázisban is felbukkan majd a Prismánál; ott is ugyanígy hívjuk.

MIT JELENT, HOGY „NINCS SZIGORÚ SZERZŐDÉS”?

A REST megmondja, hogyan címezd az erőforrásokat, de arról egy szót sem szól, milyen mezők vannak a válaszban. Semmi nem akadályozza meg a backend-fejlesztőt abban, hogy holnap átnevezze a price mezőt amount-ra — a kérés ugyanúgy 200-at fog adni, csak a mobilalkalmazásban mostantól „undefined Ft” jelenik meg.

A gRPC-nél vagy a GraphQL-nél ez nem történhet meg: ott a mezőlista géppel olvasható szerződésben van rögzítve, és a fordító azonnal szól, ha valaki elrontja. REST-nél ezt a szerződést nekünk kell pótolnunk:

  • OpenAPI-leírással, amely felsorolja a mezőket és a típusokat;
  • a válasz alakját rögzítő automatikus teszttel;
  • TypeScript-típusokkal, amelyeket a frontend és a backend is ugyanabból a forrásból kap.

A tanulság: a REST szabadsága kényelmes fejlesztés közben, de a fegyelmet nekünk kell hozzátennünk — különben az API némán romlik el a kliensek alatt.

MIT JELENT A „MEREV ERŐFORRÁS-MODELL”?

A REST abból indul ki, hogy minden művelet besorolható a négy CRUD-művelet valamelyikébe: létrehozás, olvasás, módosítás, törlés. Csakhogy a valóságban rengeteg olyan művelet van, amelyik egyik dobozba sem fér bele:

A művelet, amit szeretnénkMelyik CRUD ez?
Bejelentkezés jelszóvalNem hoz létre semmit… vagy egy „munkamenetet” igen?
Egy rendelés lemondásaMódosítás? Törlés? A rendelés megmarad, csak az állapota változik.
Elfelejtett jelszó — e-mail küldéseSemmit nem hoz létre a felhasználó szemszögéből.
Két felhasználói fiók összevonásaEgyszerre módosítás és törlés, két erőforráson.
Egy termék készletének növelése eggyelMódosítás — de az új érték a régitől függ.

Ilyenkor két úton indulhatunk el. Vagy találunk egy főnevet a művelet mögé, és létrehozzuk azt (POST /orders/42/cancellation — létrejön egy „lemondás”), vagy elfogadjuk, hogy itt kivételt teszünk, és igét használunk (POST /auth/login).

Fontos, hogy ez nem hiba, hanem kompromisszum. Aki mindenáron erőforrásokba akar gyömöszölni minden műveletet, olyan URL-eket gyárt, amit senki nem ért. A jó API elsősorban kiszámítható, és csak másodsorban elvhű.

12REST vs. a többiek

SzempontRESTGraphQLgRPCSOAP
FormátumJSON (általában)JSONBináris (Protobuf)XML
VégpontokSok (erőforrásonként)Általában egySzolgáltatás-metódusokEgy
Ki dönti el, mi jön visszaA szerverA kliensA szerződésA szerződés
Szerződés, típusokLaza (OpenAPI ajánlott)Erős (séma)Erős (.proto)Erős (WSDL)
Böngészőből hívható✅✅⚠️ csak proxyval✅
HTTP-gyorsítótár✅⚠️ nehézkes⚠️⚠️
Tanulási görbeAlacsonyKözepesKözepes-magasMagas
Tipikus felhasználásPublikus és belső web-APISokféle kliens, összetett adatSzolgáltatások közti belső hívásRégi vállalati rendszerek
MIÉRT REST-TEL KEZDÜNK?

Mert ez a legelterjedtebb, a legegyszerűbben megérthető, és mert a mögötte lévő tudás — HTTP, státuszkódok, JSON — minden másik megoldásnál is kell.

13Amiről még hallanod kell

Ezeket most csak megismerjük — a webshop-projektben mindegyikkel dolgozni fogunk.

CORS — Cross-Origin Resource Sharing

A böngésző alapból megtiltja, hogy egy oldal (http://localhost:5173) más eredetű (http://localhost:3000) API-t hívjon. A szervernek külön engedélyt kell adnia erre (Access-Control-Allow-Origin fejléc).

FIGYELEM

Ez a kezdők egyik leggyakoribb „miért nem működik?” élménye — és csak a böngészőt érinti: curl-lel vagy REST Clienttel ugyanaz a kérés simán működik. Ha tehát a böngészőben CORS-hibát látsz, de a REST Clientben minden jó, akkor nem a szerver logikájával van baj.

Hitelesítés Bearer tokennel

Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI1IiwiZXhwIjoxNzQyMH0.abc123def456ghi
                      └───── fejléc ─────┘ └──────────── adat ───────────┘ └── aláírás ──┘
                       melyik algoritmus     ki vagy, meddig érvényes      ezzel ellenőrzi
                       írta alá                                            a szerver

A JWT (JSON Web Token) három, ponttal elválasztott részből áll. Nem titkosított, csak aláírt — bárki elolvashatja a tartalmát, de módosítani nem tudja észrevétlenül.

VESZÉLY

Mivel a token tartalma olvasható, jelszót vagy más érzékeny adatot soha ne tegyünk bele. Csak azonosítót, szerepkört és lejárati időt.

Rate limiting

Korlátozzuk, hány kérést küldhet valaki adott idő alatt. Túllépés esetén 429 Too Many Requests. Véd a visszaélés és a jelszó-próbálgatás ellen.

HTTPS

Éles rendszerben kötelező. Enélkül a tokened és a jelszavad olvasható a hálózaton.

Dokumentáció — OpenAPI / Swagger

Géppel olvasható leírás az API-ról, amelyből kipróbálható dokumentációs felület és kliens-kódok generálhatók.

14Hogyan próbálj ki egy API-t?

EszközMire jóMegjegyzés
Böngésző címsoraCsak GET-reA leggyorsabb ellenőrzés
DevTools → NetworkValós kérések megfigyeléseF12, majd frissítés
curlBármilyen kérés parancssorbólWindows 10/11-en beépített
REST Client (VS Code).http fájlba írt kérésekIngyenes, verziókezelhető — ezt ajánljuk
BrunoÖnálló API-kliensIngyenes, nyílt forráskódú, fájlalapú
Postman / InsomniaÖnálló API-kliensIngyenes csomaggal is használható, de fiókot kér
# GET-kérés
curl https://jsonplaceholder.typicode.com/users/1

# GET a fejlécekkel együtt
curl -i https://jsonplaceholder.typicode.com/users/1

# POST JSON-nal (cmd-ben a folytatójel ^, PowerShellben `, Linuxon \)
curl -X POST https://jsonplaceholder.typicode.com/posts ^
  -H "Content-Type: application/json" ^
  -d "{\"title\":\"Teszt\",\"body\":\"Szöveg\",\"userId\":1}"
FIGYELEM (Windows)

PowerShellben a curl alapból az Invoke-WebRequest álneve lehet, és másképp viselkedik. Használd a curl.exe alakot, vagy dolgozz a VS Code REST Clientjével.

VS Code REST Client-fájl (keresek.http)

### Felhasználó lekérése
GET https://jsonplaceholder.typicode.com/users/1
Accept: application/json

### Új bejegyzés
POST https://jsonplaceholder.typicode.com/posts
Content-Type: application/json

{ "title": "Teszt", "body": "Szöveg", "userId": 1 }

Szimulált API-kliens

Kattints egy kérésre, és nézd meg, mit válaszolna rá a webshop API-ja. Figyeld a státuszkódot és a válasz szerkezetét! (Ez itt beégetett adatokból dolgozik, valódi hálózat nélkül.)

Kérés
Válassz egy kérést fent…
Válasz
…

15Jó és rossz API — gyakori hibák

❌ Rossz✅ JóMiért
GET /getAllProductsGET /productsAz igét a metódus adja
POST /deleteProduct?id=42DELETE /products/42Megfelelő metódus
GET /products/42/deleteDELETE /products/42A GET nem változtathat állapotot
200 { "error": "nincs jog" }403 ForbiddenA státuszkód hordozza az eredményt
POST /products → 200201 + LocationPontos jelzés a létrehozásról
/products?deleteId=42DELETE /products/42Az azonosító az útvonalba való
/product/42/reviews/list/products/42/reviewsKövetkezetes többes szám, felesleges tag nélkül
GET /login?user=a&pass=bPOST /auth/login (törzsben)Jelszó soha nem megy URL-ben
Minden hiba 500400 / 401 / 403 / 404 / 409 / 422Segít a hibakeresésben
Válasz hol tömb, hol objektumEgységes szerkezetKiszámíthatóság

Gyakori hibák — összefoglalva

HibaMiért bajHelyesen
Ige az URL-benNem erőforrás-orientáltPOST /users
Állapotváltoztatás GET-telCache vagy robot véletlenül végrehajtjaMegfelelő metódus
Mindig 200A kliens nem tudja, mi történtBeszédes státuszkódok
Token az URL-benNaplókban, előzményekben megmaradAuthorization fejléc
Stack trace a hibaválaszbanInformációszivárgásÁltalános üzenet + naplózás
Nincs validáció a szerverenA kliens megkerülhetőMinden bemenet ellenőrzése
Egyes és többes szám keveréseKiszámíthatatlan APIKövetkezetes többes szám
Nincs lapozás a listáknál100 000 rekord egy válaszbanpage + limit
Jelszó-hash visszaküldéseSúlyos biztonsági hibaSosem küldünk vissza titkot

16Feladatok

Elméleti feladatok
F1⭐ alap

Metódus és státuszkód. Add meg minden művelethez a helyes metódust, útvonalat és sikeres státuszkódot egy blog API-ban (erőforrások: posts, comments):

  • a) Összes bejegyzés listája   b) A 7-es bejegyzés lekérése   c) Új bejegyzés írása
  • d) A 7-es bejegyzés címének módosítása   e) A 7-es bejegyzés törlése
  • f) A 7-es bejegyzés kommentjei   g) Új komment a 7-es bejegyzéshez
F2⭐ alap

Státuszkód-választás. Melyik státuszkódot adnád vissza?

  • a) A kért termék nem létezik   b) A felhasználó nincs bejelentkezve
  • c) Be van jelentkezve, de nem admin   d) Az elküldött ár negatív
  • e) A regisztrációnál használt e-mail már foglalt   f) Az adatbázis nem érhető el
  • g) Sikeres törlés   h) Sikeres létrehozás
F3⭐⭐ haladó

Hibakeresés. Javítsd ki az alábbi API-tervet, és indokold soronként!

GET  /api/getAllUsers
POST /api/user/delete?id=5
GET  /api/user/5/getOrders
POST /api/login?email=a@b.hu&password=titok123
GET  /api/products/cheap
F4⭐⭐ haladó

Idempotencia. Döntsd el, idempotens-e, és indokolj!

  • a) GET /orders/3   b) POST /orders
  • c) PUT /users/5 { "name": "Anna" }
  • d) DELETE /users/5
  • e) PATCH /products/42 { "stock": { "increaseBy": 1 } }
F5⭐⭐ haladó

JSON-javítás. Keresd meg a hibákat! (Az ellenőrzéshez használd a 6. szakasz JSON-ellenőrzőjét.)

{
  nev: 'Kovács Anna',
  "kor": 17,
  "aktiv": True,
  "targyak": ["matek", "fizika",],
  // megjegyzés
  "szuletett": 2026-05-14
}
F6⭐⭐⭐ kihívás

API-terv. Tervezd meg egy iskolai könyvtár API-jának végpontjait! Erőforrások: könyvek, szerzők, olvasók, kölcsönzések. Adj meg legalább 12 végpontot metódussal, útvonallal, rövid leírással és a sikeres státuszkóddal. Gondolj a szűrésre és a lapozásra is!

F7⭐⭐⭐ kihívás

Előny-hátrány esszé. Egy cég azon gondolkodik, REST vagy GraphQL API-t készítsen a mobilalkalmazásához. Írj fél oldalt: milyen kérdéseket tennél fel nekik, és milyen esetben ajánlanád az egyiket vagy a másikat?

Gyakorlati feladatok
G1⭐ alap

Böngészős felfedezés. Nyisd meg ezeket a címeket, és jegyezd le, mit adnak vissza:

https://jsonplaceholder.typicode.com/users
https://jsonplaceholder.typicode.com/users/3
https://jsonplaceholder.typicode.com/users/3/posts
https://jsonplaceholder.typicode.com/posts?userId=3&_limit=2
https://jsonplaceholder.typicode.com/users/9999

Az utolsónál mi a státuszkód (F12 → Network)? Miért éppen az?

G2⭐⭐ haladó

Fejlécek vizsgálata. F12 → Network fülön nyiss meg egy tetszőleges oldalt, kattints az első kérésre, és írd ki:

  • a kérés metódusát és a válasz státuszkódját;
  • a válasz Content-Type fejlécét;
  • van-e Cache-Control fejléc, és mit mond;
  • mekkora a válasz mérete.
G3⭐⭐ haladó

curl. Küldj el parancssorból egy GET és egy POST kérést a jsonplaceholder.typicode.com API-nak! Mentsd el a parancsokat és a kimenetet. (A -i kapcsolóval a fejlécek is látszanak.)

G4⭐⭐⭐ kihívás

Kérésnapló. Válassz egy webshopot, nyisd meg a DevTools Network fülét, és szűrj a Fetch/XHR típusra. Tegyél valamit a kosárba, és nézd meg: milyen kérés indult (metódus, URL, státuszkód), és mit küldött a törzsében? Írd le, mit gondolsz, mit csinál ez a végpont a szerveren.

17Önellenőrző kvíz

Tíz kérdés. Válassz, és azonnal megtudod, jó volt-e — magyarázattal.

18Összegzés

  1. A HTTP kérés–válasz párokban működik; a kérés kezdősorból, fejlécekből, üres sorból és (opcionálisan) törzsből áll.
  2. A metódus mondja meg, mit teszünk (GET, POST, PUT, PATCH, DELETE), a státuszkód azt, mi lett az eredmény (2xx / 4xx / 5xx).
  3. A GET biztonságos (nem változtat); a GET, PUT, DELETE idempotens, a POST nem.
  4. A JSON a web-API-k adatformátuma: hat típus, kettős idézőjeles kulcsok, nincs komment és nincs záró vessző.
  5. A REST egy architekturális stílus: minden erőforrás, saját URL-lel, egységes HTTP-műveletekkel. Hat alapelve közül a legfontosabbak az állapotmentesség és az egységes felület.
  6. Jó URL: főnév, többes szám, kisbetű, hierarchia; szűrés és lapozás query paraméterrel.
  7. Előnyök: egyszerű, ismerős, skálázható, cache-elhető, kliensfüggetlen, jól tesztelhető. Hátrányok: over- és under-fetching, laza szerződés, verziózási teher, nincs valós idejűség.
  8. A gyakorlatban a Richardson 2. szintjét célozzuk: erőforrás-URL-ek + helyes metódusok és státuszkódok. A HATEOAS-t ismerjük, de nem használjuk.

19Fogalomtár

FogalomJelentés
HTTP
HyperText Transfer Protocol
A web kérés–válasz protokollja
Kérés / válaszKezdősor + fejlécek + üres sor + (törzs)
Metódus (ige)Mit akarunk tenni: GET, POST, PUT, PATCH, DELETE
StátuszkódHáromjegyű eredményjelző: 2xx siker, 4xx kliens-, 5xx szerverhiba
Fejléc (header)Kulcs–érték metaadat a kérésről vagy válaszról
Törzs (body)A tényleges adat, jellemzően JSON
URI / végpont
Uniform Resource Identifier
Az erőforrás címe, illetve az API egy elérési pontja
ErőforrásA REST-ben kezelt „dolog” (termék, rendelés, felhasználó)
ReprezentációAz erőforrás egy formába öntött változata (JSON)
REST
Representational State Transfer
Erőforrás-orientált architekturális stílus HTTP-re építve
StatelessA szerver nem tárol munkamenetet a kérések között
IdempotensTöbbszöri végrehajtás ugyanazt az állapotot eredményezi
Biztonságos (safe)A kérés nem változtat állapotot (GET, HEAD)
CRUDCreate, Read, Update, Delete
JSON
JavaScript Object Notation
Szöveges adatcsere-formátum
CORS
Cross-Origin Resource Sharing
Böngészőbeli szabály a más eredetű kérésekre
Bearer tokenAz Authorization fejlécben küldött hitelesítő jegy (pl. JWT)
Rate limitingKérésszám-korlátozás; túllépéskor 429
OpenAPI / SwaggerGéppel olvasható API-dokumentáció
HATEOAS
Hypermedia As The Engine Of Application State
A válasz linkeket ad a lehetséges következő lépésekhez
← Előző tananyag 1. A backend fogalma