<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xml" href="/cjs/screen.xsl" media="screen"?>
<lecture>

<meta>
  <maintitle>Sítě</maintitle>
  <author>Jiří Znamenáček</author>
  <title>Protokol HTTP</title>
  <date>2012-xx-xx</date>
  <link><!--a href="http://vyuka.ookami.cz" rel="external">http://vyuka.ookami.cz</a--></link>
</meta>
<!--
  „“–…
  ←→ ↑↓ ↔↕
  ↵ aneb &#x21B5; aneb \r aneb CR aneb CarriageReturn
-->


<slide title="Úvod">

  <p>
    Jak už název napovídá (HTTP = <em>HyperText Transfer Protocol</em>), byl <strong>síťový protokol HTTP</strong> vytvořen pro přenos HTML-souborů a dalších s ním souvisejících zdrojů (jako jsou například obrázky, skripty či stylová data; obecně tzv. <em>resources</em>) mezi klientem a serverem.
  </p>
  <p>
    Veškerá tato komunikace probíhá na <a href="?slajd=4">textové úrovni</a> a je v základu <a href="?slajd=3">bezestavová</a>.
  </p>
  <p>
    Dnes je převážně používána verze protokolu <em>HTTP 1.1</em>, která je sice poněkud komplikovanější na tvorbu a obsluhu než verze <em>1.0</em>, ale podstatně lépe využívá zdrojů a prostředků – mimo jiné umožňuje využít mezipaměti (<em>cache</em>) a zasílat data, aniž by byla dopředu známa jejich celková délka (tzv. <em>chunked encoding</em>).
  </p>
  <note>
    Výklad veden volně podle <a href="http://jmarshall.com/easy/http/" class="external">HTTP Made Really Easy</a> a <a href="http://www.w3.org/Protocols/rfc2616/rfc2616.html" class="external">standardu HTTP/1.1</a>.
  </note>

</slide>
<slide title="Příklad – dotaz „GET“">

  <p>
    Jak jsme si už ukazovali v kapitole <a href="overview.xml?slajd=3">o práci webového prohlížeče</a>, základním dotazem, který můžeme po protokolu HTTP poslat z klienta na HTTP-server je dotaz <code>GET</code> na konkrétní cílový zdroj:
  </p>
  <example lang="http">
GET / HTTP/1.1         # získání zdroje z umístění „/“ metodou GET
Host: www.python.org   # dodatečná hlavička dotazu
↵                      # prázdná řádka (ukončuje dotaz)
  </example>
  <p>
    Na uvedený <em>textový</em> dotaz v našem případě server odpověděl následující <em>textovou</em> odpovědí:
  </p>
  <example lang="http">
# hlavička odpovědi
HTTP/1.1 200 OK
Date: Wed, 01 Dec 2010 16:17:20 GMT
Server: Apache/2.2.9 (Debian) DAV/2 SVN/1.5.1 mod_ssl/2.2.9 OpenSSL/0.9.8g mod_wsgi/2.5 Python/2.5.2
Last-Modified: Wed, 01 Dec 2010 11:59:27 GMT
ETag: "105800d-49e3-49658097825c0"
Accept-Ranges: bytes
Content-Length: 18915
Connection: close
Content-Type: text/html
↵   # prázdná řádka – ukončuje hlavičku, následují vlastní data odpovědi
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


&lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

&lt;head>
  &lt;meta http-equiv="content-type" content="text/html; charset=utf-8" />
  &lt;title>Python Programming Language – Official Website&lt;/title>
  ...   # zbytek dat byl vynechán
  </example>

</slide>
<slide title="HTTP-transakce">

  <p>
    Shrňme si přechozí ukázku komunikace mezi <em>HTTP-klientem</em> a <em>HTTP-serverem</em>:
  </p>
  <ol>
    <li>
        klient naváže spojení se serverem
    </li>
    <li>
        klient zašle na server svůj <strong>požadavek</strong> (<em>request message</em>)
    </li>
    <li>
        server zpracuje požadavek od klienta a zašle nazpátek <strong>odpověď</strong> (<em>response message</em>)
    </li>
    <li>
        server ukončí spojení
    </li>
  </ol>
  <p>
    Poslední bod znamená, že HTTP-protokol je <strong>bezestavový</strong> (<em>stateless</em>) – server si v základním nastavení podle standardu mezi jednotlivými transakcemi neudržuje a nepamatuju žádné informace (o jednotlivých klientech a jejich dotazech)! Na druhou stranu s pomocí nejrůznějších prostředků je možné tuto základní vlastnost HTTP-protokolu celkem obejít a svým způsobem z něj udělat protokol stavový.
  </p>

</slide>
<slide title="Struktura zprávy">

  <p>
    Jak <strong>dotaz</strong> (<em>request</em>), tak <strong>odpověď</strong> (<em>response</em>) mají prakticky stejnou strukturu:
  </p>
  <ol>
    <li>
        úvodní řádka zprávy
        <note>Zde se od sebe dotaz a odpověď nejvíce odlišují.</note>
    </li>
    <li>
        posloupnost hlavičkových řádek
        <note>V HTTP/1.1 alespoň jedna, v HTTP/1.0 se komunikace obešla prakticky bez nich.</note>
    </li>
    <li>
        prázdná řádka
        <note>Je představována právě dvěma znaky <code>CRLF</code> (tedy sekvencí <code>\r\n</code>).</note>
    </li>
    <li>
        nepovinné tělo zprávy
        <note>Může být různě dlouhé a kromě textových může obsahovat klidně i binární data.</note>
    </li>
  </ol>

</slide>
<slide title="Úvodní řádka zprávy">

  <p>
    <em>Úvodní řádka zprávy</em> má tři části (navzájem oddělené mezerami), jejichž význam se liší podle typu/směru dotazu/odpovědi. Řádka končí posloupností znaků <code>CRLF</code> (ale programy by si měly poradit i se samotným <code>LF</code>):
  </p>
  
  <p class="enumerate">
    Úvodní řádka <strong>požadavku</strong> (<em>request</em>) má následující strukturu:
  </p>
  <blockquote>
    metoda &#160; lokální-cesta-ke-zdroji &#160; verze-protokolu↵
  </blockquote>
  <p>
    Příklady:
  </p>
  <example lang="http">
    GET / HTTP/1.1
  </example>
  <note>
    Dotaz na kořenový zdroj.
  </note>
  <example lang="http">
    GET /materialy/net/http.xml HTTP/1.1
  </example>
  <note>
    Dotaz na zdroj v umístění <code>/materialy/net/http.xml</code> od kořene.
  </note>
  
  <p class="enumerate">
    Úvodní řádka <strong>odpovědi</strong> (<em>response</em>), též zvaná <em>status line</em>, má následující strukturu:
  </p>
  <blockquote>
    verze-protokolu &#160; kód-odpovědi &#160; popis-odpovědi↵
  </blockquote>
  <p>
    Příklady:
  </p>
  <example lang="http">
    HTTP/1.1 200 OK
  </example>
  <note>
    Na dotaz bylo úspěšně odpovězeno (resp. bude v těle této odpovědi).
  </note>
  <example lang="http">
    HTTP/1.1 404 Not Found
  </example>
  <note>
    Odpověď na dotaz není úspěšná, protože požadovaný zdroj se nepodařilo nalézt.
  </note>

</slide>
<slide title="Hlavičkové řádky">

  <p>
    Hlavičkové řádky mají všechny stejnou strukturu (definovanou v <a href="http://tools.ietf.org/html/rfc822#section-3.2" class="external">RFC 822</a>):
  </p>
  <blockquote>
    jméno-hlavičky: &#160; hodnota↵
  </blockquote>
  <p>
    Platí pro ně následující pravidla:
  </p>
  <ul>
    <li>
        končí posloupností znaků <code>CRLF</code> (ale programy by si měly poradit i se samotným <code>LF</code>)
    </li>
    <li>
        jméno hlavičky nerozpoznává velká a malá písmena
    </li>
    <li>
        počet mezer mezi jménem s dvojtečkou a vlastní hodnotou není významný
    </li>
    <li>
        řádky začínající mezerou nebo tabulátorem jsou pokračováním hodnoty předchozí řádky
    </li>
  </ul>
  
  <p>
    Protokol HTTP/1.1 (bez rozšíření) definuje 47 hlaviček, z nich pouze jedna jediná (<em>Host:</em> u dotazu) je skutečně povinná. Další slouží k určení dodatečných informací o dotazu nebo odpovědi, a to včetně informací o těle zprávy.
  </p>
  <p>
    Pro detailnější přehled (i nestandardních) hlaviček se podívejte třeba na <a href="http://en.wikipedia.org/wiki/List_of_HTTP_headers" class="external">Wikipedii</a>.
  </p>

</slide>
<slide title="Hlavičkové řádky – příklad">

  <p>
    Příklad hlaviček ze skutečné komunikace mezi klientem a serverem pří načtení této stránky:
  </p>
  <example lang="http">
# požadavek: GET /materialy/net/http.xml HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:11.0) Gecko/20100101 Firefox/11.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
Referer: http://localhost/index.web.html
If-Modified-Since: Sun, 15 Apr 2012 23:48:35 GMT
If-None-Match: "4f8b5e53.2f99"
Cache-Control: max-age=0

# odpověď
HTTP/1.1 200 OK
Date: Mon, 16 Apr 2012 05:25:47 GMT
Last-Modified: Mon, 16 Apr 2012 05:09:30 GMT
Etag: "4f8ba98a.3502"
Content-Type: text/xml
Content-Length: 13570
Connection: keep-alive
Accept-Ranges: bytes 
  </example>
  <p>
    Pár komentářů k <em>požadavku</em>:
  </p>
  <ul>
    <li>
        <code>Host</code> – povinná hlavička dotazu; určuje kořenovou adresu dotazu
    </li>
    <li>
        <code>Accept</code> – typy odpovědi, které klient umí zpracovat
    </li>
    <li>
        <code>Accept-Encoding</code> – typy komprese odpovědi, které klient umí rozkódovat
    </li>
    <li>
        <code>Referer</code> – adresa předchozí stránky, ze které jsme se dostali na tento zdroj
    </li>
    <li>
        <code>If-Modified-Since</code> – nebyl-li zdroj modifikován od uvedeného data, může server vrátit odpověď <em>304 Not Modified</em> a klient může použít verzi z keše
    </li>
  </ul>
  <p>
    Pár komentářů k <em>odpovědi</em>:
  </p>
  <ul>
    <li>
        <code>Date</code> – datum odeslání odpovědi
    </li>
    <li>
        <code>Last-Modified</code> – datum modifikace zdroje (ve formátu podle <a href="http://tools.ietf.org/html/rfc2822#section-3.3" class="external">RFC 2822</a>)
    </li>
    <li>
        <code>Content-Type</code> – MIME-typ odpovědi (tedy těla odpovědi)
    </li>
    <li>
        <code>Content-Length</code> – délka těla odpovědi v bajtech
    </li>
    <li>
        <code>Accept-Ranges</code> – podporované typy rozsahů, s jakými dokáže server odpovědět na požadavek (tedy že je schopen poslat z těla odpovědi vybraný rozsah)
    </li>
  </ul>

</slide>
<slide title="Tělo zprávy">

  <p>
    <strong>Tělo zprávy</strong> slouží ke dvěma účelům:
  </p>
  <ul>
    <li>
        K přenosu vlastního zdroje (respektive odpovědi daného zdroje) zpět ke klientovi.
    </li>
    <li>
        K přenosu potřebných dat při dotazu od klienta směrem na server.
        <note>Tohle je místo, kterým se přenáší data z vyplněných formulářů nebo třeba aploudované soubory.</note>
    </li>
  </ul>
  <p>
    Obsahuje-li zpráva <em>tělo</em>, zpravidla ho v hlavičkové části doprovází následující dvě hlavičky:
  </p>
  <ul>
    <li>
        <strong>Content-Type</strong> – MIME-typ přenášených dat (zda je to HTML-text nebo JPEG-obrázek apod.)
        <note>Zde se server nebo klient dozví typ dat, což potřebuje k rozhodnutí, jak s nimi naložit.</note>
    </li>
    <li>
        <strong>Content-Length</strong> – velikost těla v bajtech
        <note>Zde se server nebo klient dozví délku dat, která potřebuje načíst.</note>
    </li>
  </ul>

</slide>
<slide title="Metody I">

  <p>
    Protokol HTTP/1.1 definuje (bez rozšíření) <strong>osm základních metod</strong>, které může klient aplikovat při zasílání požadavku:
  </p>
  <ol>
    <li>
        <strong>OPTIONS</strong> – vyžádá si vrácení HTTP-metod, které server pro daný zdroj podporuje
        <note>Užitečné pro zjištění podporovaných metod. A to i v rámci celého serveru, je-li jako zdroj zaslán řetězec <code>*</code>.</note>
    </li>
    <li>
        <strong>GET</strong> – požaduje zaslání konkrétního zdroje
        <note>Tato metoda by z konvence na serveru neměla nic měnit (tedy neměla by mít žádné vedlejší efekty), prostě by jen měla vrátit požadovaný zdroj.</note>
    </li>
    <li>
        <strong>HEAD</strong> – jako GET, ale v odpovědi bude pouze hlavičková část zprávy, tělo nebude zasíláno
        <note>Velmi výhodné pro získání metainformací (v podobě návratových hlaviček) o požadovaném zdroji, aniž by se musel celý (potenciálně velmi velký) zdroj přenášet.</note>
    </li>
    <li>
        <strong>POST</strong> – zasílá serveru data ke zpracování
        <note>Tedy dané URI zpracuje obdržená data.</note>
    </li>
    <li>
        <strong>PUT</strong> – zasílá serveru data k uložení (pokud dané URI neexistuje) nebo modifikaci (pokud dané URI existuje)
        <note>V kontrastu k metodě <em>POST</em> je dané URI změněno obdrženými daty.</note>
    </li>
    <li>
        <strong>DELETE</strong> – zasílá serveru požadavek na vymazání uvedeného zdroje
    </li>
    <li>
        <strong>TRACE</strong> – zašle nazpět obraz požadavku
        <note>Porovnáním zaslaného a vráceného dotazu si může klient ověřit, zda se s ním (tedy jeho hlavičkami a tělem) cestou něco nestalo. Typicky např. síťové keše doplňují procházející data o svoji identifikaci (což by ovšem měla být nekonfliktní úprava).</note>
    </li>
    <li>
        <strong>CONNECT</strong> – vyhrazeno pro převod navázané komunikaci mezi klientem a serverem přes nekryptěnou proxy na tunel
        <note>Užíván často k zajištění zabezpečené komunikace.</note>
    </li>
  </ol>

</slide>
<slide title="Metody II">

  <p>
    Z hlediska své (alespoň zamýšlené) aplikace a vlivu na server se HTTP-metody rozlišují podle dalších dvou hledisek:
  </p>
  
  <p class="enumerate">
    <strong>Metody bezpečné:</strong> Tyto metody <em>by neměly</em> změnit stav serveru, měly by si čistě pouze vyžádat vrácení požadovaného zdroje.
  </p>
  <p>
    Typicky mezi ně patří <code>HEAD</code>, <code>GET</code>, <code>OPTIONS</code> a <code>TRACE</code>, ale obzvláště metoda <em>GET</em> často „zlobí“ a webové aplikace ji zneužívají k nejrůznějším dalším operacím.
  </p>
  
  <p class="enumerate">
    <strong>Metody idempotentní:</strong> Jejich vícenásobná aplikace <em>by měla</em> mít stejný efekt jako aplikace pouze jediná.
  </p>
  <p>
    Typicky vícenásobná aplikace metod <code>PUT</code> a <code>DELETE</code> už by více neměla změnit stav serveru. Podobně aplikace bezpečných metod <code>HEAD</code>, <code>GET</code>, <code>OPTIONS</code> a <code>TRACE</code> by stav serveru neměla měnit vůbec, takže by měly být idempotentní automaticky (ovšem pozor na <em>GET</em> ve stejném smyslu jako výše).
  </p>

</slide>
<slide title="Kódy odpovědí">

  <p>
    Kódy odpovědí jsou přesně zadefinovaná třímístná čísla z pěti obecnějších kategorií:
  </p>
  <ol>
    <li>
        <strong>1xx</strong> – <em>informační</em>; participují zvláště na údržbě spojení při komplikovanějších transakcích podle HTTP/1.1
    </li>
    <li>
        <strong>2xx</strong> – <em>úspěch</em>; požadavek klienta byl úspěšně přijat, zpracován a je na něj zasílána odpovídající odpověď
    </li>
    <li>
        <strong>3xx</strong> – <em>přesměrování</em>; dokončení zpracování požadavku vyžaduje z nejrůznějších důvodů (zdroj byl přesunut na jinou adresu, zdroj se od udaného data nezměnil…) další spolupráci klienta
    </li>
    <li>
        <strong>4xx</strong> – <em>chyba klienta</em>; klient zřejmě zaslal z nejrůznějších důvodů (chyba formátování, dotaz na neexistující zdroj…) špatný požadavek
    </li>
    <li>
        <strong>5xx</strong> – <em>chyba serveru</em>; při zpracování požadavku došlo k chybě na straně serveru, který tak není schopen správně odpovědět
    </li>
  </ol>

</slide>
<slide title="Kódy odpovědí – příklady">

  <p>
    Typickými kódy, se kterými se můžete bězně setkat, jsou například:
  </p>
  <ul>
    <li>
        <code>100 Continue</code> – server obdržel hlavičku dotazu a čeká na její tělo
    </li>
    <li>
        <code>200 OK</code> – standardní hlášení o úspěšném zpracování požadavku
    </li>
    <li>
        <code>304 Not Modified</code> – zdroj nebyl od klientem uvedeného data změněn (klient tedy může využít zakešovanou verzi zdroje, má-li ji k dispozici)
    </li>
    <li>
        <code>404 Not Found</code> – požadovaný zdroj se na serveru (v dané chvíli) nevyskytuje
    </li>
    <li>
        <code>500 Internal Server Error</code> – generické hlášení o chybě na straně serveru
    </li>
  </ul>
  <p>
    Pro detailnější přehled (i nestandardních) návratových kódů se podívejte třeba na <a href="http://en.wikipedia.org/wiki/List_of_HTTP_status_codes" class="external">Wikipedii</a>.
  </p>

</slide>
<slide title="Slovník vybraných termínů">

  <dl>
    <dt>URI</dt>
      <dd><em>Uniform Resource Identifier</em>; jistá sekvence znaků tvořící identifikátor příslušného zdroje</dd>
    <dt>URL</dt>
      <dd><em>Uniform Resource Locator</em>; ta podmnožina URI, pro kterou je nejvýznamější částí adresa zdroje</dd>
    <dt>URN</dt>
      <dd><em>Uniform Resource Name</em>; ta podmnožina URI, pro kterou je nejvýznamější částí jméno zdroje</dd>
    <dt>MIME</dt>
      <dd><em>Multipurpose Internet Mail Extensions</em>; specificky ale způsob označování typů dokumentů (a to včetně abstraktních obálek nad více zdroji apod.)</dd>
    <dt>RFC</dt>
      <dd><em>Request For Comments</em>; memoranda publikovaná skupinou <em>Internet Engineering Task Force</em> (IETF), některá z nich se stávají internetovými standardy</dd>
  </dl>

</slide>


</lecture>
