Než napíšeš jediný řádek backendu, musíš rozumět tomu, co se vlastně stane, když někdo otevře tvůj web. Zadáš adresu, zmáčkneš Enter — a za zlomek vteřiny se načte stránka. Mezitím proběhne několik kroků na několika různých technologiích. Tahle kapitola je projde všechny, pomalu a od nuly. Je to úplný základ: odkazuje se na něj každá další kapitola, tak ho neproskakuj.
Pár pojmů na úvod (ať se neztratíš)
Backend je program, který běží na nějakém počítači připojeném k internetu (tomu počítači se říká server) a odpovídá na požadavky. Ten, kdo se ptá — prohlížeč, mobilní aplikace — je klient.
- Request (požadavek) = zpráva od klienta serveru: „pošli mi domovskou stránku", „ulož tuhle objednávku".
- Response (odpověď) = zpráva, kterou server pošle zpátky: stránka, data, nebo hlášení o chybě.
- Protokol = dohodnutá pravidla, jak spolu klient a server mluví, aby si rozuměli (např. HTTP).
- IP adresa = číselná adresa počítače v síti, podobně jako adresa domu. Třeba
104.21.5.7. - Port = číslo „dveří" na tom počítači. Na jedné IP může běžet víc služeb a každá poslouchá na svém portu (web má výchozí porty 80 pro HTTP a 443 pro HTTPS — proto je v URL nevidíš; ale je to jen konvence, lokální dev běží třeba na 3000 nebo 8080).
Celý backend ve své podstatě dělá jen tohle: přišel request → něco s ním udělej → vrať response. Pořád dokola, klidně milionkrát za den. Všechno ostatní v téhle učebnici je jen rozpracování téhle jedné věty.
Co se stane, když zadáš adresu (mentální model)
Když do prohlížeče napíšeš adresu a dáš Enter, proběhnou zhruba tyhle kroky, než vůbec uvidíš stránku:
Nelekej se pojmů v diagramu — projdeme je teď jeden po druhém v tomhle pořadí: DNS → TCP → TLS → HTTP. Až to dočteš, vrať se sem a diagram ti dá smysl celý. (Reverse proxy, CDN a load balancer si vysvětlíme níže a hlavně v dalších kapitolách — zatím ber, že je to „pár serverů, které stojí před tvojí aplikací".)
1. DNS — překlad jména na adresu
Lidi si pamatují jména (google.com), ale počítače se v síti hledají podle IP adres. DNS
(Domain Name System) je telefonní seznam internetu: dáš mu jméno a vrátí ti IP adresu.
Takže úplně první věc, kterou prohlížeč udělá, není stažení stránky — je to dotaz: „jakou IP adresu
má google.com?" Teprve když zná IP, ví, kam se vůbec připojit.
- Odpovědi se cachují (dočasně ukládají) na spoustě míst — v prohlížeči, v operačním systému, u tvého poskytovatele internetu — aby se nemusel stejný překlad dělat znovu a znovu.
- TTL (Time To Live) říká, jak dlouho se smí odpověď cachovat, než si ji musí vyžádat znovu. Krátké TTL = změny se projeví rychle, ale je víc dotazů. Dlouhé TTL = míň dotazů, ale změna se „rozjíždí" pomaleji.
- Kdo se koho ptá: tvůj počítač se ptá rekurzivního resolveru (u poskytovatele / veřejného jako 1.1.1.1), a ten teprve obejde hierarchii root → TLD (.cz) → autoritativní server domény. Cache je hlavně na tom resolveru — proto změnu na registrátorovi „nevidíš" hned.
- Typický zmatek začátečníka: přesměruješ doménu jinam a „nefunguje to" — přitom se ti jen ještě
chvíli servíruje stará IP z cache. Není to bug, je to TTL. A pozor — cachují se i negativní
odpovědi (NXDOMAIN), takže „přidal jsem záznam a chvíli to nešlo" je taky normální. (Příkaz
dig example.comv terminálu ti ukáže, jakou IP doména právě vrací.)
Pro úplnost, druhy DNS záznamů (zatím stačí vědět, že existují): A = IPv4 adresa, AAAA = IPv6 adresa, CNAME = „tahle doména je přezdívka jiné", MX = kam doručovat e-maily, TXT = textová poznámka (často pro ověření vlastnictví domény).
2. TCP — navázání spolehlivého spojení
Teď, když prohlížeč zná IP, musí se k serveru připojit. Data se po internetu posílají v malých kouscích zvaných pakety — představ si dlouhý dopis rozstříhaný na pohlednice, které putují každá zvlášť a můžou dorazit v jiném pořadí (nebo se cestou ztratit).
- IP se stará jen o doručení paketů z bodu A do bodu B — bez záruky, že dorazí všechny a ve správném pořadí.
- TCP je vrstva nad IP, která tu nespolehlivost schová: pakety seřadí, ztracené pošle znovu a zařídí, aby na druhé straně vyšel kompletní, správně poskládaný proud dat. Proto se mu říká spolehlivý protokol.
Než si spolu dva začnou „povídat", musí se nejdřív pozdravit — tomu se říká handshake:
Klient: „Slyšíš mě?" (SYN)
Server: „Jo, a ty mě?" (SYN-ACK)
Klient: „Jo, jedeme." (ACK)
Tenhle pozdrav stojí jeden round-trip (cesta tam a zpět), a to je čas. Proto se navázaná spojení snaží znovupoužívat místo otevírání nového na každý request. Tahle drobnost je zdrojem překvapivě velké části výkonových problémů — třeba otevírat nové spojení do databáze na každý požadavek je „malá" chyba s velkým dopadem (víc v kapitole Concurrency a Performance & Scaling).
UDP je bratříček TCP, který tyhle záruky nemá — pakety prostě vystřelí a nestará se, jestli dorazily. Zní to špatně, ale pro video hovory, hry nebo právě DNS je to výhra: radši rychle a občas ztratit paket než čekat na potvrzení. Klíčová myšlenka: vědět, kdy obětovat spolehlivost za rychlost.
3. TLS / HTTPS — zašifrování a ověření
To „s" v https znamená secure. Bez něj by si kdokoli na cestě mezi tebou a serverem (Wi-Fi v
kavárně, tvůj poskytovatel) mohl přečíst i změnit, co posíláš. TLS to řeší dvěma věcmi naráz:
- Šifrování — data putují jako v zalepené obálce, kterou po cestě nikdo nepřečte.
- Ověření identity — server se prokáže certifikátem, takže máš jistotu, že mluvíš se
skutečným
mojebanka.cz, a ne s podvrženým serverem útočníka. Certifikátu věříš proto, že ho podepsala důvěryhodná autorita (CA), které věří už tvůj prohlížeč.
Tohle ověření je další handshake a stojí další round-tripy (novější TLS 1.3 to zkrátil). Je to další důvod, proč je drahé navazovat spojení pořád znovu.
Časté problémy, na které narazíš: expirovaný certifikát (platnost mají omezenou, musí se obnovovat) nebo špatně nakonfigurovaný řetěz certifikátů — prohlížeč pak ukáže to varování o „nedůvěryhodném připojení".
4. HTTP — vlastní jazyk requestů
Konečně se dostáváme k samotné konverzaci. HTTP je protokol, kterým si klient a server řeknou, co chtějí. Každý request má:
- metodu (co chci dělat — viz níže),
- cestu (
/courses/42— který zdroj), - hlavičky (headers — doplňující informace, např. v jakém formátu chci data),
- volitelně tělo (body — data, která posílám, třeba obsah nové objednávky).
A každá response má status kód (jak to dopadlo), hlavičky a tělo (data nebo HTML).
„Stateless" — server tě po každém requestu zapomene
HTTP je stateless (bezstavový): server si mezi jednotlivými requesty nic nepamatuje. Každý request musí přijít se vším kontextem, který server potřebuje — hlavně „kdo jsem". Proto s každým požadavkem posíláš znovu cookie nebo token — je to jako ukazovat lístek pokaždé, když projdeš turniketem, protože tě obsluha mezi průchody nepozná.
Zní to jako nevýhoda, ale je to obrovská výhoda: když si server nedrží žádný osobní stav, může tvůj request obsloužit kterýkoli ze serverů — a to je přesně to, co umožňuje přidávat servery a škálovat (víc o tom v Performance & Scaling).
Metody — co chci s daty dělat
| Metoda | Co znamená | Bezpečná (jen čte)? | Idempotentní? |
|---|---|---|---|
| GET | přečti zdroj | ✅ | ✅ |
| POST | vytvoř / proveď akci | ❌ | ❌ |
| PUT | nahraď celý zdroj | ❌ | ✅ |
| PATCH | uprav část zdroje | ❌ | záleží |
| DELETE | smaž zdroj | ❌ | ✅ |
U PATCH „záleží" znamená podle toho, co děláš: PATCH {stav: "zaplaceno"} (nastavení na pevnou
hodnotu) je idempotentní, ale PATCH {pocet: pocet + 1} (přičtení) idempotentní není.
Idempotentní je slovo, které uvidíš v téhle učebnici pořád, tak hned na začátku jednoduše: operace je idempotentní, když ji provedeš dvakrát a výsledek je stejný jako jednou. Smazat objednávku #5 dvakrát = pořád je smazaná (idempotentní). Ale poslat „zaplať 500 Kč" dvakrát = dvě platby (NEidempotentní!). Proto se u plateb řeší speciálně — viz Patterny.
Status kódy — jak to dopadlo
Server v každé odpovědi vrací třímístné číslo. Stačí znát skupiny:
- 2xx = povedlo se.
200OK,201vytvořeno,204OK ale bez dat. - 3xx = přesměrování.
301trvale jinam,302dočasně jinam,304„nezměnilo se, použij cache". (Past: po301/302může prohlížeč změnit POST na GET;307/308původní metodu zachovají.) - 4xx = chyba na straně klienta (request je špatně).
400špatný request,401nepřihlášen,403přihlášen, ale nemá právo,404neexistuje,409konflikt,422neprošla validace,429moc requestů (rate limit). - 5xx = chyba na straně serveru (server to pokazil).
500interní chyba,502/503/504problémy s nedostupností nebo timeoutem (odpověď nepřišla včas — viz dole u TCP).
Nejčastější záměna: 401 vs 403. 401 = „nevím, kdo jsi" (přihlas se). 403 = „vím, kdo jsi, ale na tohle nemáš právo". Plést si je je klasická juniorská chyba.
Hlavičky, které potkáš
Hlavičky jsou doplňkové info ke každému requestu/response. Pár, které uvidíš pořád:
Content-Type (v jakém formátu jsou data, např. JSON), Authorization (token, kterým se prokazuješ),
Cache-Control (jak dlouho se smí odpověď cachovat — viz Caching).
Verze HTTP (jen ať víš, že existují)
HTTP/1.1 je stará klasika. HTTP/2 umí poslat víc požadavků přes jedno spojení naráz (multiplexing). Jenže běží nad TCP, kde ztráta jednoho paketu pozdrží všechny streamy (TCP head-of-line blocking) — a přesně to řeší HTTP/3 tím, že běží nad UDP (QUIC). To je celý důvod jeho existence. Jako junior nemusíš řešit detaily, ale tahle pointa „proč HTTP/3" stojí za zapamatování.
Cookies a sessions — jak si tě server „pamatuje"
Řekli jsme, že HTTP je stateless a server tě po každém requestu zapomene. Jak tedy zůstaneš přihlášený? Přes cookie — malý kousek dat, který server pošle prohlížeči, a ten ho pak automaticky přikládá ke každému dalšímu requestu na ten web. Funguje to dvěma způsoby:
- Session cookie — v cookie je jen náhodné ID session, podle kterého si server v paměti/databázi
najde, kdo jsi. Stav je na serveru. (Pozor: to ID je samo o sobě tajemství — kdo ho ukradne, je
přihlášený za tebe, tomu se říká session hijacking. Proto
HttpOnlyníže.) - Token v cookie — v cookie je rovnou token, který nese informaci o tobě (detaily v Security).
U cookies si pak hlídáš tři bezpečnostní nastavení (víc v Security): HttpOnly (cookie nepřečte JavaScript → ochrana před krádeží), Secure (posílá se jen po HTTPS) a SameSite (omezí, kdy se cookie přikládá → ochrana před CSRF).
Cachování a komprese — ať se nepřenáší zbytečně
Dvě hlavičky, kterými server šetří přenos (víc v Caching):
Cache-Controlříká prohlížeči (a CDN), jak dlouho si smí odpověď schovat, aby ji nestahoval pořád dokola.ETag+If-None-Matchje „otisk" verze obsahu. Prohlížeč při dalším dotazu pošle otisk, který má; když se nezměnil, server odpoví krátkým304 Not Modifiedmísto posílání celých dat znovu.
A komprese (gzip/brotli): server odpověď před odesláním zmenší a prohlížeč ji rozbalí — menší data putují sítí rychleji. Většinou to zapne server sám.
CORS — proč ti volání projde v terminálu, ale ne v prohlížeči
Tohle tě dřív nebo později „kousne", tak ať víš dopředu. CORS je bezpečnostní pravidlo
prohlížeče (ne tvého serveru!). Prohlížeč z principu nedovolí, aby JavaScript na webu A.cz volal
server na B.cz, pokud to server B.cz výslovně nepovolí speciální hlavičkou.
Důsledek, který mate každého: úplně stejný požadavek projde z terminálu (příkazem curl), ale
v prohlížeči spadne na CORS chybu. Není to bug v tvém kódu — curl totiž žádné takové bezpečnostní
pravidlo nemá, kdežto prohlížeč ano. Řešení je doplnit na serveru správné CORS hlavičky.
Failure modes — jak to v praxi „praská"
Tyhle tři chyby vypadají podobně, ale každá znamená něco jiného. Umět je rozlišit = umět rychle najít příčinu:
- Connection refused — na druhé straně nikdo neposlouchá (služba neběží, nebo voláš špatný port).
- Timeout — spojení se navázalo, ale odpověď nepřišla včas (server je přetížený, nebo na něčem zaseknutý).
- Connection reset — spojení bylo násilně přerušeno (něco po cestě ho zabilo, server spadl).
A jedna past, na kterou tě připraví zbytek učebnice: slepě opakovat (retry) neidempotentní POST po timeoutu může vést k duplicitní akci — třeba dvě platby. Proto se requesty a opakování musí navrhovat s rozmyslem (viz Patterny → Idempotency).
🛠️ Cvičení
Pár cvičení používá nástroje, které možná vidíš poprvé (DevTools v prohlížeči,
curl,digv terminálu). To je záměr — nejlíp se to naučíš tím, že si na ně sáhneš.
- Sleduj reálný request. V prohlížeči otevři vývojářské nástroje (F12) → záložka Network, načti
libovolný web a najdi: status kód, hlavičku
Content-Typea (v záložce Timing) jak dlouho trval TLS handshake. - Zkus
digacurl. V terminálu spusťdig example.com(uvidíš IP adresu) acurl -v https://example.com(uvidíš handshake i hlavičky requestu a response). Najdi v outputu status kód. - Vyrob si CORS chybu. Na libovolném webu otevři konzoli (F12 → Console) a napiš
fetch('https://example.org'). Přečti chybovou hlášku a vysvětli, proč by stejné volání přescurlprošlo. - Zařaď status kódy. Ke každé situaci přiřaď kód: nepřihlášený uživatel, přihlášený bez práv, neexistující stránka, neprošla validace formuláře, spadl server, příliš mnoho requestů.
- Idempotence v praxi. U každého rozhodni, jestli je bezpečné poslat to dvakrát, a proč:
GET /orders/5,DELETE /orders/5,POST /orders,PUT /orders/5.
Náčrt řešení — rozbal, až si cvičení zkusíš sám
- Sleduj reálný request — v Network panelu klikni na konkrétní request, status najdeš v záhlaví,
Content-Typev Response headers a TLS čas v záložce Timing („SSL"). Pozor: TLS čas uvidíš jen u prvního spojení — další requesty ho znovupoužijí (proto je 0), tak hledej ten první, na který se navazuje. - Zkus
digacurl—digti vypíše A záznam (IP),curl -vukáže celý handshake i hlavičky; status kód je první řádek odpovědi (HTTP/2 200). Na co pozor: řádky začínající*jsou diagnostika spojení (DNS/TCP/TLS),>je tvůj request,<je response — neplést si je. - Vyrob si CORS chybu —
fetchspadne, protožeexample.orgnepošle hlavičkuAccess-Control-Allow-Origin, takže prohlížeč odpověď zablokuje. Klíčová pointa: blokuje prohlížeč, ne server —curlžádné CORS pravidlo nemá, proto stejné volání projde. Nejde o chybu v kódu, ale o chybějící povolení na serveru. - Zařaď status kódy — nepřihlášený
401, přihlášený bez práv403, neexistující stránka404, neprošlá validace422, spadlý server500, příliš requestů429. Klasická past: nepřihlášenému vracet403místo401(401 = „nevím kdo jsi", 403 = „vím, ale nesmíš"). - Idempotence v praxi —
GET,PUTiDELETEjdou opakovat bez vzniku duplicit (jsou idempotentní),POST /ordersne (každé volání vytvoří novou objednávku). Pozor: nepleť „idempotentní" se „safe" — safe je jen metoda, co vůbec nemění stav (GET);PUT/DELETEstav mění, jen opakování nepřidá nic navíc.DELETEje idempotentní co do stavu (po prvním je smazáno), i když druhé volání může vrátit404— to nevadí.
🧠 Otázky & odpovědi
Proč volání projde v curlu, ale v prohlížeči spadne na CORS?
CORS je bezpečnostní pravidlo prohlížeče, ne vlastnost serveru. Prohlížeč zakáže JavaScriptu volat
jiný web, dokud to ten web výslovně nepovolí hlavičkou (Access-Control-Allow-Origin). curl v
terminálu žádné takové pravidlo nemá, takže prostě pošle požadavek. Proto „v curlu to jede, v appce ne" —
a proto to není chyba v tvém kódu, ale chybějící povolení na serveru.
Jaký je rozdíl mezi 401 a 403?
401 Unauthorized = „nevím, kdo jsi" — chybí nebo je neplatné přihlášení, takže se přihlas. 403 Forbidden = „vím, kdo jsi, ale na tohle nemáš právo" — jsi přihlášený, ale nemáš oprávnění. Častá chyba je vracet 403 tam, kde je uživatel jen nepřihlášený.
Co znamená, že je HTTP stateless, a proč je to výhoda?
Server si mezi requesty nic nepamatuje — každý požadavek musí přinést všechen kontext sám (kdo jsem → cookie/token). Výhoda: protože si žádný server nedrží „tvůj" stav, může tě obsloužit kterýkoli z nich. Stav se ukládá mimo (do databáze nebo cache), takže když přidáš další servery, hned zvládneš víc uživatelů. To je základ horizontálního škálování.
Proč je drahé otevírat nové spojení a co s tím?
Navázat spojení znamená udělat TCP handshake a (u HTTPS) i TLS handshake — to jsou cesty tam a zpět, tedy čas, plus alokace zdrojů. Když otevíráš nové spojení na každý požadavek (třeba do databáze), platíš tu cenu pokaždé a navíc můžeš vyčerpat limit spojení. Řešení je spojení znovupoužívat (connection pooling — drží se sada otevřených spojení a recyklují se).
Rozliš connection refused, timeout a connection reset.
Refused = na druhé straně nikdo neposlouchá (služba neběží nebo voláš špatný port). Timeout = spojení se navázalo, ale odpověď nepřišla včas (přetížení, zaseknutí). Reset = spojení bylo násilně přerušeno (něco po cestě ho ukončilo, server spadl). Každé ukazuje na jinou příčinu, takže je neházej do jednoho pytle — rozlišení ti ušetří hodiny debugování.
Když je HTTP stateless, jak zůstanu přihlášený?
Přes cookie — malý kousek dat, který server pošle prohlížeči a ten ho automaticky přikládá ke každému dalšímu requestu na ten web. V cookie bývá buď ID session (server si podle něj najde, kdo jsi), nebo rovnou token nesoucí informaci o tobě. Server tě tak při každém requestu „pozná", aniž by si mezi nimi cokoli pamatoval.
Co je ETag a co znamená 304 Not Modified?
ETag je „otisk" verze obsahu, který server pošle s odpovědí. Při dalším dotazu prohlížeč ten otisk
přiloží zpátky; když se obsah nezměnil, server místo posílání celých dat odpoví krátkým 304 Not Modified = „nic nového, použij, co máš v cache". Šetří to přenos i čas — nestahuje se znovu něco,
co se nezměnilo.
