Vezérlőpult
5. Kérés és válasz · Express alapok

Express alapok · 5. tananyag

Kérés és válasz

Az előző fejezetben megtanultuk, melyik kezelőfüggvény fut le. Most az a kérdés, hogy mit tudunk meg a kérésből, és hogyan válaszolunk rá pontosan — beleértve azt, ami eddig hiányzott: a kérés törzsét.

3 tanóraexpress.json()Egy kérésre egy válasz

A fejezet végén tudni fogod

1A req objektum — mit tudunk meg a kérésről?

A kezelőfüggvény első paramétere a kérés. Az Express kiegészíti a Node http moduljának kérésobjektumát — az eredeti tulajdonságok (req.method, req.url, req.headers) továbbra is megvannak, de jóval kényelmesebb eszközöket is kapunk.

POST /api/products?ertesites=true HTTP/1.1 Host: localhost:3000 Content-Type: application/json (üres sor) {"nev": "Egér", "ar": 4990} POST req.method "POST" mindig nagybetűvel /api/products req.path "/api/products" query NÉLKÜL ?ertesites=true req.query { ertesites: "true" } minden érték szöveg Content-Type: req.get(…) "application/json" bármelyik fejléc {"nev": …} req.body { nev, ar } CSAK middleware-rel! req.params Nem a kérésből jön, hanem az ÚTVONALMINTÁBÓL: a /:id szakasz értéke — lásd a 4. fejezetet. A SZABÁLY, AMI MINDENHOL IGAZ A params, a query és az űrlapadat értéke MINDIG szöveg. Csak a JSON törzsben marad a szám szám.
1. ábra — Egy kérés, öt objektum: a színek párosítják őket. A req.body az egyetlen, amihez middleware kell.
app.get("/info", (req, res) => {
  res.json({
    metodus:  req.method,        // "GET"
    utvonal:  req.path,          // "/info"        — query NÉLKÜL
    teljes:   req.originalUrl,   // "/info?a=1"    — ahogy a kliens kérte
    protokoll: req.protocol,     // "http"
    hoszt:    req.hostname,      // "localhost"
    ip:       req.ip             // "::1"
  });
});

A leggyakrabban használt tulajdonságok

TulajdonságMit ad?Megjegyzés
req.methodA HTTP-metódus nagybetűvel"GET", "POST"…
req.pathAz útvonal query nélkül/api/products
req.originalUrlA kliens által kért teljes útvonalNaplózáshoz ezt használd
req.paramsÚtvonalparaméterek (4. fejezet)Mindig szöveg
req.queryQuery paraméterek (4. fejezet)Szöveg vagy szövegtömb
req.bodyA kérés törzse — csak middleware-rel!Erről szól a 2. szakasz
req.protocol"http" vagy "https"
req.hostnameA megszólított hostlocalhost
req.ipA kliens IP-címeHelyben ::1 — ez az IPv6 „localhost”
MIÉRT ::1 ÉS NEM 127.0.0.1?

Mert a böngésző és a Node ma alapból IPv6-on éri el a localhost-ot. A ::1 az IPv6 saját-gép címe, ugyanaz, mint IPv4-ben a 127.0.0.1.

Fejlécek olvasása: req.get()

req.get("Content-Type");   // "application/json; charset=utf-8"
req.get("content-type");   // ugyanaz — NEM érzékeny a kis- és nagybetűre
req.get("User-Agent");     // ki küldte a kérést
req.get("Authorization");  // a token — a 4. blokkban lesz fontos

Ugyanezt megkapod a req.headers objektumból is, de ott csak kisbetűs kulccsal (req.headers["content-type"]). A req.get() ennél barátságosabb: mindkét írásmódot elfogadja.

A tartalom típusának vizsgálata: req.is()

req.is("application/json");   // "application/json"  — ha egyezik
req.is("json");               // "json"              — rövid alak is jó
req.is("html");               // false               — ha nem egyezik
VIGYÁZZ: NEM true-T AD VISSZA!

Egyezés esetén magát a típus szövegét adja vissza, különben false-t. Ez így is működik if feltételben (a nem üres szöveg igaz értékű), de ha === true-val hasonlítanád össze, sosem lenne igaz.

2A kérés törzse: express.json()

A 2. fejezetben így olvastuk be a törzset — most nézd meg, mennyivel rövidebb Expressben:

2. fejezet — http modulKÉZZEL
let torzs = "";

for await (const darab of req) {
  torzs += darab;
}

const adat = JSON.parse(torzs);
// …és minden végpontnál újra
ExpressEGY SOR
app.use(express.json());

// …ezután MINDEN végpontban:
req.body   // { nev: "Egér", ar: 4990 }
const app = express();

app.use(express.json());          // ← ez az egy sor

app.post("/api/products", (req, res) => {
  console.log(req.body);          // { nev: "Egér", ar: 4990 }
  res.status(201).json({ letrehozva: req.body });
});

Mit csinál pontosan?

Az express.json() egy middleware: minden kérés előtt lefut. Négy dolgot végez el:

BEÉRKEZŐ KÉRÉS POST /api/products 1. Content-Type? application/json? nem Hozzá sem nyúl a törzshöz req.body === undefined igen 2. Törzs beolvasása darabonként, streamből túl nagy 413 Payload Too Large entity.too.large 3. JSON.parse szövegből objektum hibás 400 Bad Request entity.parse.failed req.body = { … } A HÁROM KIMENET Objektum — minden rendben volt. undefined — a middleware hozzá sem nyúlt (rossz vagy hiányzó fejléc, vagy nincs is express.json()). Hiba — a kezelőfüggvény el sem indul, a hibakezelő válaszol helyette. Egy negyedik eset: helyes fejléc + üres törzs → {}
2. ábra — Az express.json() útja. Innen érthető meg, miért lesz néha undefined a req.body.
LépésMit tesz?
1.Megnézi a Content-Type fejlécet — csak application/json esetén dolgozik
2.Darabonként beolvassa a törzset (ugyanaz a stream, mint a 2. fejezetben)
3.JSON.parse-szal objektummá alakítja
4.Az eredményt a req.body tulajdonságba teszi
A MIDDLEWARE FOGALMÁVAL A 6. FEJEZET FOGLALKOZIK

Itt elég annyi: az app.use(…) sorba tett függvény minden kérésnél lefut, még az útvonalak előtt. A sorrend számít: az express.json()-nek az útvonalak előtt kell állnia.

Ha kihagyod: req.body az undefined

Ez a fejezet leggyakoribb hibája. express.json() nélkül:

POST /api/products
Content-Type: application/json

{"nev":"Egér","ar":4990}
app.post("/api/products", (req, res) => {
  console.log(req.body);          // undefined
  console.log(req.body.nev);      // ❌ TypeError: Cannot read properties of undefined
});

Kipróbálva: a typeof req.body értéke "undefined" — a törzs ott van a hálózaton, csak senki nem olvasta be.

A TÜNET FELISMERÉSE

Ha a hibaüzenet így hangzik: TypeError: Cannot read properties of undefined (reading 'nev'), és a req.body-ra vonatkozik, akkor majdnem biztosan hiányzik az app.use(express.json()) sor — vagy az útvonalak után áll.

Ugyanez rossz Content-Type fejléccel

Az express.json() csak akkor dolgozik, ha a kliens application/json típust jelzett. Ha a fejléc hiányzik vagy más:

Amit a kliens küldreq.body értéke
Content-Type: application/json, érvényes JSONa feldolgozott objektum
Content-Type: application/json, üres törzs{} — üres objektum
Nincs Content-Type fejlécundefined
Content-Type: text/plainundefined

Mindegyik sor kipróbált eredmény (Express 5.2.1). Vedd észre a második és a harmadik sor különbségét: az üres objektum azt jelenti, hogy a middleware dolgozott, de nem talált adatot; az undefined azt, hogy hozzá sem nyúlt a törzshöz.

EZÉRT KELL A REST CLIENTBEN A FEJLÉC

Ha a .http fájlból lehagyod a Content-Type: application/json sort, a szerver oldalon undefined lesz a req.body — és percekig a szerverkódban keresnéd a hibát, pedig a kérés volt hiányos.

Beállítási lehetőségek

Az express.json() paraméter nélkül is jól működik, de érdemes tudni, mit lehet állítani:

KulcsLehetséges értékekAlapértékMit csinál?
limitméret szövegként ("100kb", "1mb") vagy bájtszám"100kb"A törzs megengedett legnagyobb mérete. Fölötte 413-as hiba
typeMIME-típus vagy típuslista"application/json"Melyik Content-Type esetén dolgozzon a middleware
stricttrue / falsetruetrue esetén csak objektumot és tömböt fogad el a törzsben; false esetén sima szöveget és számot is
inflatetrue / falsetrueKicsomagolja-e a tömörített (gzip) törzset

Példák a strict beállításra:

Törzsstrict: true (alapérték)strict: false
{"a":1}✅ objektum✅ objektum
[1,2]✅ tömb✅ tömb
"csak szoveg"❌ 400-as hiba✅ a "csak szoveg" szöveg

Az alapértékek jók — ezeket ne állítsd át, amíg nincs rá konkrét okod. A limit az egyetlen, amit fájlfeltöltésnél jellemzően emelni kell (arról a 4. blokkban lesz szó).

3Amikor a törzs hibás

Három tipikus eset, mindhárom tesztelt eredménnyel.

Hibás JSON → 400

POST /api/products
Content-Type: application/json

{"nev": hibas}

Az express.json() nem hívja meg a kezelőfüggvényt, hanem hibát dob tovább. A hibaobjektum:

{
  "name": "SyntaxError",
  "message": "Unexpected token 'h', \"{\"nev\": hibas}\" is not valid JSON",
  "status": 400,
  "type": "entity.parse.failed"
}

Túl nagy törzs → 413

Ha a törzs nagyobb, mint a limit:

{
  "name": "PayloadTooLargeError",
  "message": "request entity too large",
  "status": 413,
  "type": "entity.too.large"
}

A 413 jelentése: Payload Too Large — „túl nagy a küldött tartalom”.

Mit lát a kliens?

Ha nincs saját hibakezelőd, az Express beépített hibakezelője válaszol. Ez HTML-t küld — API-ban ez nem az, amit szeretnénk. Ezért írunk saját hibakezelőt:

// a lánc LEGVÉGÉN, minden útvonal után
app.use((err, req, res, next) => {
  res.status(err.status || 500).json({
    error: {
      message: err.message,
      type: err.type          // pl. "entity.parse.failed"
    }
  });
});

Ez a négyparaméteres függvény a központi hibakezelő. Az Express onnan ismeri fel, hogy négy paramétere van (az első az err). A teljes hibakezelés a 8. fejezet témája — itt csak annyi a lényeg, hogy a törzs-feldolgozás hibái is ide futnak be.

A type MEZŐ HASZNOS

Ebből tudod megkülönböztetni, hogy hibás volt-e a JSON (entity.parse.failed), túl nagy volt-e (entity.too.large), vagy valami egészen más történt. A kliensnek viszont ne add oda a nyers err.message szöveget éles rendszerben — arról is a 8. fejezetben lesz szó.

4Űrlapadat: express.urlencoded()

A HTML-űrlapok alapból nem JSON-t küldenek, hanem application/x-www-form-urlencoded formátumot — ugyanazt, amit a query stringben látunk:

nev=Eger&ar=4990

Ehhez másik middleware kell:

app.use(express.json());                              // JSON-hoz
app.use(express.urlencoded({ extended: false }));     // űrlaphoz

Mindkettő nyugodtan ott lehet egyszerre: mindegyik csak a saját Content-Type-jára reagál.

Az extended beállítás

KulcsLehetséges értékekMit csinál?
extendedfalseCsak lapos kulcs-érték párokat ért. Egyszerűbb, kevesebb meglepetés
trueBeágyazott szerkezetet is felismer (a[b]=1 → { a: { b: "1" } })

A különbség az a[b]=1&c=2 törzsre:

Beállításreq.body
extended: false{ "a[b]": "1", "c": "2" } — a szögletes zárójel a kulcs része
extended: true{ "a": { "b": "1" }, "c": "2" } — beágyazott objektum lesz belőle

Mi az extended: false-t használjuk, mert egy JSON API-ban az űrlapadat úgyis csak kiegészítés, és az egyszerűbb viselkedés kevesebb meglepetést okoz.

MINDEN ÉRTÉK SZÖVEG — MEGINT

Az ar=4990 törzsből { ar: "4990" } lesz, szövegként. Ugyanaz a szabály, mint a req.params és a req.query esetében. JSON-nál viszont nem így van: ott a {"ar":4990} valódi számot ad.

Mi lesz a req.body?

Hat helyzet: a middleware, a Content-Type fejléc és a törzs különböző kombinációi. Döntsd el, mit kap a kezelőfüggvény!

1 / 6Helyes: 0
…

5A válasz fejlécei

A státuszkóddal és a törzzsel az előző fejezetekben már foglalkoztunk. Nézzük a harmadik részt:

app.get("/api/products/42", (req, res) => {
  res.set("X-Osszes-Talalat", "128");        // saját fejléc
  res.json(termek);
});
MetódusMit csinál?Példa
res.set(nev, ertek)Beállít egy fejlécetres.set("Cache-Control", "no-store")
res.set({ … })Több fejlécet egyszerreres.set({ "A": "1", "B": "2" })
res.get(nev)Visszaolvassa, mit állítottál beres.get("Content-Type")
res.type(típus)A Content-Type fejléc rövidebbenres.type("json")
res.location(útvonal)A Location fejléc beállításares.location("/api/products/9")

Mikor kell ez a gyakorlatban?

HelyzetFejléc
Létrehozás után megmondani, hol az új erőforrásLocation: /api/products/9
Lapozásnál az összes találat számasaját fejléc, pl. X-Total-Count
Megtiltani a válasz gyorsítótárazásátCache-Control: no-store

A 201-es válasz teljes, szabályos alakja:

app.post("/api/products", (req, res) => {
  const ujTermek = { id: 9, ...req.body };

  res.location(`/api/products/${ujTermek.id}`);   // hol találod meg?
  res.status(201).json(ujTermek);
});
EMLÉKEZTETŐ AZ 1. BLOKK 2. FEJEZETÉBŐL

A 201 Created válasz mellé illik Location fejléc, hogy a kliens tudja, hova került az új erőforrás. Ez része a REST „szerződésnek”.

A saját fejlécek X- előtagja

Régen minden nem szabványos fejlécet X- előtaggal illett kezdeni (X-Total-Count). Ma ezt már nem írja elő szabvány, de a gyakorlatban máig ez a legelterjedtebb szokás, és jól megkülönbözteti a saját fejléceidet a szabványosaktól. Mi is így írjuk.

6Amit a res.json() átalakít

A res.json() a háttérben JSON.stringify-t hív — és annak megvannak a maga szabályai. A tapasztalat alapján:

Amit írsz (JS-objektum)
res.json({
  datum:    new Date(0),
  nincs:    undefined,
  semmi:    null,
  vegtelen: Infinity,
  nan:      NaN
});
Amit a kliens kap (JSON)TESZTELVE
{
  "datum": "1970-01-01T00:00:00.000Z",

  "semmi": null,
  "vegtelen": null,
  "nan": null
}
Amit írszAmi elmegyMiért?
new Date(0)"1970-01-01T00:00:00.000Z"Szöveggé alakul, ISO formátumban
undefineda kulcs eltűnikA JSON nem ismeri az undefined értéket
nullnullEz rendben van, a JSON ismeri
InfinitynullA JSON nem ismeri a végtelent
NaNnullA JSON nem ismeri a „nem szám” értéket
A KÉT VESZÉLYES SOR

Az undefined értékű mező egyszerűen nem jelenik meg a válaszban — a kliens azt hiszi, hogy nem is létezik. A NaN pedig null-lá válik: ha egy számítás elromlott, a hiba null alakban jut el a klienshez, és nehéz lesz megtalálni.

Ezért érdemes kiszámított értékeket ellenőrizni, mielőtt elküldöd őket:

const atlag = Number.isFinite(szamitott) ? szamitott : 0;

A dátum ISO-szövegként megy — ez jó hír: szabványos, egyértelmű, időzónafüggetlen. A kliens oldalon a new Date("1970-01-01T00:00:00.000Z") visszaalakítja.

Mi megy el a válaszban?

Öt mező. Döntsd el mindegyikről, milyen alakban érkezik meg a klienshez.

1 / 5Helyes: 0
…

7Egy kérésre egy válasz

Ez a HTTP alapszabálya, és a 2. fejezetben már találkoztunk vele. Expressben így néz ki a hiba:

app.get("/api/products/:id", (req, res) => {
  const termek = keres(req.params.id);

  if (!termek) {
    res.status(404).json({ error: { message: "Nincs ilyen termék." } });
    // ❌ hiányzik a return!
  }

  res.json(termek);          // lefut ez is
});

Mit lát a kliens, és mit látsz te?

Ez fontos különbség a 2. fejezethez képest, és ellenőriztük is:

IDŐVONAL → res.status(404).json(…) 1. válasz — ELMEGY res.json(termek) 2. válasz — ELBUKIK ERR_HTTP_HEADERS_SENT „a fejlécek már elmentek” 2. FEJEZET — http MODUL A kliens: megkapja az első választ. A szerver: LEÁLL. A terminál: hibaüzenet, majd kilépés. Feltűnő — rögtön észreveszed. EXPRESS A kliens: megkapja az első választ (404). A szerver: FUT TOVÁBB. A terminál: hibaüzenet, a munka folytatódik. Alattomosabb — semmi nem szól érte.
3. ábra — Ugyanaz a hiba, két különböző következmény.

A terminálban ez jelenik meg:

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (node:_http_outgoing:684:11)
    at ServerResponse.header (…\node_modules\express\lib\response.js:686:10)
    at ServerResponse.send (…\node_modules\express\lib\response.js:163:12)
    at ServerResponse.json (…\node_modules\express\lib\response.js:252:15)
EZ ALATTOMOSABB, MINT A LEÁLLÁS

Mivel a szerver fut tovább és a kliens is kapott választ, semmi nem hívja fel rá a figyelmedet — csak a terminálban gyűlnek a hibák. Ezért érdemes a szerver kimenetét munka közben is szemmel tartani.

A megoldás: return

if (!termek) {
  return res.status(404).json({ error: { message: "Nincs ilyen termék." } });
}

res.json(termek);

A return res.… írásmód azért terjedt el, mert egy sorban intézi el mindkettőt: elküldi a választ és kilép a függvényből. A res.json() visszatérési értékét nem használjuk semmire — a return itt csak a kilépés miatt van.

Védekezés: res.headersSent

if (!res.headersSent) {
  res.status(500).json({ error: { message: "Váratlan hiba." } });
}
TulajdonságÉrtéke
res.headersSent a küldés előttfalse
res.headersSent a küldés utántrue

Javaslat: a headersSent helyett használjuk inkább a return-t. A headersSent a hibakezelőben hasznos, ahol tényleg nem tudhatod, mi történt korábban.

8Átirányítás — és miért ritka az API-ban

res.redirect("/api/products");         // alapból 302
res.redirect(301, "/api/termekek");    // saját kóddal

Az eredmény a res.redirect(302, "/info") hívásra:

302  Location: /info
Content-Type: text/plain; charset=utf-8
Found. Redirecting to /info
KódJelentésMikor?
301Végleges átirányításAz erőforrás véglegesen máshova került
302Ideiglenes átirányításAlkalmi átirányítás (ez az alapérték)
JSON API-BAN EZT SZINTE SOHA NEM HASZNÁLJUK

Az átirányítás a böngészőnek szól: az automatikusan követi. Egy API-kliens (mobilalkalmazás, másik szerver) nem feltétlenül teszi ezt meg. API-ban inkább 404-et vagy 410 Gone kódot adunk, és a válasz törzsében mondjuk meg, hol az új cím.

9Egységes válaszformátum a webshophoz

Ha minden végpont máshogy formázza a hibát, a kliensoldali kód használhatatlan lesz. Rögzítsük most, és a blokk végéig tartsuk magunkat hozzá:

Sikeres válasz — maga az adat, becsomagolás nélkül:

{ "id": 42, "nev": "Billentyűzet", "ar": 12990 }
[ { "id": 42, "nev": "Billentyűzet" }, { "id": 43, "nev": "Egér" } ]

Hibás válasz — mindig ugyanaz a szerkezet:

{
  "error": {
    "message": "Nincs ilyen termék.",
    "code": "TERMEK_NEM_TALALHATO"
  }
}
MezőKinek szól?Példa
messageEmbernek — a fejlesztőnek vagy a felhasználónak"Nincs ilyen termék."
codeGépnek — a kliensoldali kód ezt vizsgálja"TERMEK_NEM_TALALHATO"
MIÉRT KELL A code IS?

Mert az üzenet szövege bármikor megváltozhat (elgépelés javítása, fordítás), a kód viszont állandó. Ha a kliens az üzenet szövegére épít, az első átfogalmazás eltöri. Ha a kódra épít, nem.

Egy segédfüggvény, amit a blokk végéig használunk:

// valaszok.js
export function hiba(res, statusz, uzenet, kod) {
  return res.status(statusz).json({ error: { message: uzenet, code: kod } });
}
import { hiba } from "./valaszok.js";

app.get("/api/products/:id", (req, res) => {
  const id = Number(req.params.id);
  if (Number.isNaN(id)) return hiba(res, 400, "Az azonosító csak szám lehet.", "ERVENYTELEN_ID");

  const termek = termekek.find(t => t.id === id);
  if (!termek) return hiba(res, 404, "Nincs ilyen termék.", "TERMEK_NEM_TALALHATO");

  res.json(termek);
});

Figyeld meg, hogy a hiba() visszaadja a res.status(…).json(…) eredményét — így működik előtte a return, és nem kell két sorba írni.

EMLÉKEZTETŐ AZ 1. BLOKK 2. FEJEZETÉBŐL

Létezik szabványos hibaformátum is: az RFC 9457 Problem Details, application/problem+json típussal. A miénk annak egy egyszerűbb, saját változata — kisebb projektben ez teljesen elfogadott, ha következetes.

10Gyakori hibák

req.body az undefined

Tünet: TypeError: Cannot read properties of undefined (reading 'nev')

Három lehetséges ok, ebben a sorrendben ellenőrizd:

OkMegoldás
Hiányzik az app.use(express.json())Vedd fel, az útvonalak elé
Az express.json() az útvonalak után állTedd fel a fájl elejére
A kliens nem küldött Content-Type: application/json fejlécetJavítsd a .http fájlt vagy a klienst

A szám szövegként érkezik

app.post("/api/products", (req, res) => {
  const ar = req.body.ar;              // JSON-nál szám, űrlapnál SZÖVEG
});

JSON törzsből a {"ar":4990} valódi számot ad, űrlapadatból viszont (ar=4990) szöveget. Ha mindkettőt fogadod, alakíts át: Number(req.body.ar).

ERR_HTTP_HEADERS_SENT

Tünet: a kliens megkapja az első választ, a terminálban viszont hibaüzenet jelenik meg.
Ok: hiányzik egy return a korai válasz elől.
Megoldás: return res.status(404).json(…).

Az ékezetek elromlanak

Expressben ez ritka, mert a res.json() magától charset=utf-8 fejlécet küld. Ha mégis előfordul, akkor jellemzően res.set("Content-Type", "text/plain") volt kézzel beállítva, charset nélkül.

A mező eltűnik a válaszból

res.json({ nev: termek.nev, leiras: termek.leiras });   // ha a leiras undefined…

Ha a termek.leiras értéke undefined, a leiras kulcs egyáltalán nem jelenik meg a válaszban. Ha a kliensnek tudnia kell, hogy a mező létezik, de üres, írj oda null-t:

res.json({ nev: termek.nev, leiras: termek.leiras ?? null });

11Feladatok

Elméleti

F1⭐Honnan jön az adat?

Egy POST /api/categories/3/products?ertesites=true kérés törzse {"nev":"Egér"}. Melyik objektumban találod meg: req.params, req.query vagy req.body?

  • a) a 3
  • b) az ertesites értéke
  • c) a nev értéke
  • d) a /api/categories/3/products útvonal
F2⭐Mi lesz a req.body?

Döntsd el mindegyik esetről:

  • a) Content-Type: application/json, törzs: {"a":1}
  • b) Content-Type: application/json, törzs: üres
  • c) nincs Content-Type fejléc, törzs: {"a":1}
  • d) Content-Type: application/json, törzs: {"a":}
  • e) app.use(express.json()) nélkül, minden más rendben
F3⭐⭐Hibakeresés

Mi a hiba, mit lát a kliens, és mit látsz te a terminálban?

app.get("/api/products/:id", (req, res) => {
  const termek = keres(Number(req.params.id));
  if (!termek) {
    res.status(404).json({ error: { message: "Nincs ilyen." } });
  }
  res.json(termek);
});
F4⭐⭐Mi megy el?

Mit kap pontosan a kliens erre a válaszra? Magyarázd meg soronként!

res.json({
  id: 42,
  letrehozva: new Date("2026-03-01T10:00:00Z"),
  leiras: undefined,
  keszlet: 0,
  atlagErtekeles: 0 / 0
});
F5⭐⭐⭐Tervezz hibaformátumot

Írd le a webshop API összes hibaesetét (érvénytelen azonosító, nem létező termék, hiányzó kötelező mező, túl nagy törzs, hibás JSON), és mindegyikhez add meg a státuszkódot, az üzenetet és a kódot. Indokold, miért pont azt a státuszkódot választottad!

Gyakorlati

G1⭐Kérésnapló

Készíts egy GET /api/echo végpontot, amely JSON-ban visszaadja a kérés metódusát, útvonalát, query paramétereit és a User-Agent fejlécet. Próbáld ki böngészőből és REST Clientből is, és hasonlítsd össze a User-Agent értékét!

G2⭐⭐Termék létrehozása

Készíts egy POST /api/products végpontot, amely:

  • beolvassa a törzset (express.json()),
  • ellenőrzi, hogy van-e nev és ar mező (ha nincs → 400, egységes hibaformátumban),
  • ellenőrzi, hogy az ar szám-e és pozitív-e (ha nem → 400),
  • eltárolja egy tömbben, és 201-gyel + Location fejléccel válaszol.
G3⭐⭐Hibás törzs kezelése

Írj központi hibakezelőt, amely a hibás JSON-t (400) és a túl nagy törzset (413) is a saját, egységes hibaformátumodban adja vissza. Állítsd a limit értékét 1kb-ra, és bizonyítsd be REST Clienttel, hogy mindkét eset működik!

G4⭐⭐Fejlécek

Bővítsd a GET /api/products végpontot úgy, hogy egy X-Total-Count fejlécben visszaadja az összes találat számát (lapozás előtt). Ellenőrizd REST Clientben, hogy a fejléc tényleg megjelenik a válaszban!

G5⭐⭐⭐Kétféle bemenet

Fogadj a POST /api/products végponton JSON-t és űrlapadatot is. Gondoskodj róla, hogy az ar mindkét esetben számként kerüljön a tárolóba. Írj hozzá két .http kérést, és bizonyítsd be, hogy mindkettő ugyanazt az eredményt adja!

12Önellenőrző kvíz

0 / 10 megválaszolva

13Összegzés

  1. A req objektumból az útvonalon és a query stringen túl a fejlécekhez (req.get()), a tartalom típusához (req.is()) és a klienshez (req.ip) is hozzáférünk.
  2. A kérés törzsét az express.json() middleware olvassa be, és a req.body objektumba teszi. Az útvonalak elé kell tenni.
  3. Nélküle — vagy hiányzó Content-Type fejléc esetén — a req.body értéke undefined. Ez a fejezet leggyakoribb hibája.
  4. A hibás törzs 400-as, a túl nagy törzs 413-as hibát okoz. Mindkettő a központi hibakezelőhöz kerül — saját hibakezelő nélkül az Express HTML-t küldene vissza.
  5. Az express.urlencoded() az űrlapadatot dolgozza fel; ott minden érték szöveg, míg a JSON-nál a szám szám marad.
  6. A válaszban fejlécet a res.set(), res.type() és res.location() metódusokkal állítunk. A 201-es válasz mellé Location fejléc jár.
  7. A res.json() átalakít: a dátumból ISO-szöveg lesz, az undefined mező eltűnik, a NaN és az Infinity pedig null lesz.
  8. Egy kérésre egy válasz. Expressben a második válasz nem állítja le a szervert — csak a terminálban jelenik meg az ERR_HTTP_HEADERS_SENT hiba. A megoldás: return a korai válasz elé.
  9. A webshop API egységes formátumot használ: sikernél maga az adat, hibánál { error: { message, code } }.

14Fogalomtár

FogalomJelentés
express.json()Middleware, amely a JSON törzset feldolgozza és a req.body-ba teszi
express.urlencoded()Ugyanez űrlapadathoz (application/x-www-form-urlencoded)
req.bodyA feldolgozott kéréstörzs — middleware nélkül undefined
req.get(nev)Fejléc olvasása, kis- és nagybetűre érzéketlenül
req.is(típus)Megvizsgálja a törzs típusát; a típus szövegét vagy false-t ad
req.pathAz útvonal query nélkül
req.originalUrlA kliens által kért teljes útvonal
res.set(nev, ertek)Válaszfejléc beállítása
res.location(útvonal)A Location fejléc beállítása
res.headersSentIgaz, ha a válasz már elment
ERR_HTTP_HEADERS_SENTHibakód: kétszer próbáltál válaszolni ugyanarra a kérésre
413 Payload Too LargeA kérés törzse nagyobb a megengedettnél
entity.parse.failedHibatípus: a törzs nem érvényes JSON
← Előző 4. Útvonalak (routing)