Protokol HTTP 1.1

Protokol HTTP

Protokol http (HyperText Transfer Protocol) je protokolem, kterým mezi sebou komunikují klienti a servery systému WWW. Popisu protokolu http byla sice věnována část předcházejícího seriálu o systému WWW, ale protože nová verze protokolu přináší zcela nové vlastnosti, budeme se mu v tomto článku věnovat podrobněji. Protokol http je v současné době implementován pouze nad protokolem TCP/IP, ale obecně vystačí s libovolným protokolem, který poskytuje spojované služby. První verze protokolu vznikla při vývoji systému WWW ve středisku CERN. Původní protokol pouze umožňoval klientovi navázat spojení se serverem, zaslat požadavek ve tvaru GET <URL>, přečíst odpověď a uzavřít spojení. Server pouze přijal požadavek, zpracoval jej a odeslal požadovaný dokument nebo zprávu o chybě:

Tento protokol byl později formálně definován jako protokol http verze 0.9 (RFC 1945). Brzy se ukázalo, že natolik jednoduchý protokol nestačí. Pro přenos atributů dokumentu bylo nezbytné doplnit tělo dokumentu doprovodnými hlavičkami. Pro přenos atributů dokumentu bylo využito již existujícího standardu Multipurpose Internet Mail Extensions (MIME, RFC1521) pro přenos dokumentů elektronickou poštou. Princip funkce protokolu zůstal nezměněn a tak vznikl protokol http verze 1.0 (RFC 1945). Pro kompatibilitu s původním protokolem byl zachován začátek prvního řádku požadavku:

První řádek požadavku klienta byl doplněn o číslo verze protokolu http, kterou klient zvládá. Rovněž první řádek odpovědi serveru obsahuje číslo verze protokolu http, kterou zvládá server, a tak se mohou server i klient domluvit s protějšky, které komunikují jinou verzí protokolu. Na dalších řádcích požadavku i odpovědi následují hlavičky, které jsou ukončeny prvním prázdným řádkem. Protokol http verze 1.0 definuje pouze požadavky GET, HEAD a POST. Požadavek GET slouží k získání požadovaného dokumentu a byl ilustrován na předcházejících příkladech. Požadavkem HEAD může klient získat hlavičky odpovědi serveru, které by server zaslal při požadavku GET na daný dokument. Klient tak může z těchto hlaviček zjistit, zda se dokument od posledního přenosu nezměnil.

Požadavkem POST může klient předat data serveru. Data následují za prvním prázdným řádkem po hlavičkách požadavku. Většinou se jedná o data předaná jako odpověď na formulář. U tohoto požadavku musí klient správně signalizovat délku předaných dat hlavičkou Content-Length, protože server nemůže jiným způsobem rozpoznat konec dat. Server hlavičku Content-Length generovat nemusí, protože klient rozezná konec dat podle toho, že server ukončil spojení. Klient ale v tomto případě nepozná, zda byl přenos dokončen celý.

Protokol http verze 1.1

Definice nové verze protokolu http prošla mnoha zásadními změnami. Pokud se podíváte do starších čísel Connectu! na seriál o systému WWW, asi zjistíte, že některé dále popisované vlastnosti poněkud nesouhlasí. Následující popis totiž vychází z nedávno publikovaného dokumentu RFC 2068 (ftp://ds.internic.net/rfc/rfc2068.txt), zatímco předcházející články vycházely z prvních návrhů. Protokol http verze 1.1 je v současné době ve stadiu implementace. Začínají se objevovat první servery, které komunikují tímto protokolem, a nové verze prohlížečů Netscape a Internet Explorer by jej také měly podporovat. Nová verze protokolu http přináší tyto uživatelsky významné novinky: Nový protokol je rozšířením protokolu http verze 1.0. Každý klient a server zvládající protokol verze 1.1 musí být schopen komunikovat všemi nižšími verzemi protokolu.

Protokol je rozšířen o požadavky uložení dokumentu na server (PUT) a zrušení dokumentu (DELETE). Další typy požadavků zůstávají volitelným rozšířením: modifikace dokumentu (PATCH), vytvoření vazby (LINK) a zrušení vazby (UNLINK). Poslední dva požadavky by společně s vhodným zpracováním mohly vyřešit principiální nedostatek systému WWW, údržbu konzistence odkazů. Server by mohl při vložení dokumentů zaregistrovat všechny odkazy z dokumentu a při případných přesunech a rušení varovat uživatele.

Udržované spojení

Protokol http verze 1.0 měl stále omezení původního jednoduchého protokolu - nedovoloval při jednom spojení se serverem získat více dokumentů. Při původním použití systému WWW to příliš nevadilo, dokumenty obsahovaly pouze text a odkazy na další navazující dokumenty. Dnešní dokumenty naproti tomu často obsahují desítky vložených obrázků a pro zobrazení těchto dokumentů musí klient přenést nejen vlastní dokument, ale také všechny vložené obrázky. Klient je získává protokolem http a proto musí vygenerovat tolik požadavků, kolik je v dokumentu obrázků. Sekvenční generování požadavků trvá poměrně dlouho, protože u přenosu malého objemu dat trvá nejdéle navázání spojení. Většina klientů proto generuje pro přenos vložených obrázků paralelně několik požadavků. Přesto nelze ani při této metodě využít teoretické přenosové kapacity spoje. Souvisí to s vlastnostmi protokolu TCP, který je optimalizován spíše pro déletrvající souvislý přenos dat při jednom spojení, než pro krátké, nezávisle spojované přenosy. Protokol http verze 1.1 řeší tento problém zavedením udržovaného spojení, které není ukončeno po zpracování jednoho požadavku.

Udržované spojení bylo zavedeno jako volitelné rozšíření již v protokolu http verze 1.0, ale vzhledem k problémům v některých implementacích (např. Netscape 2.0) se příliš nerozšířilo. Mezi mechanismy udržovaného spojení v obou verzích protokolu je zásadní rozdíl. Zatímco u protokolu 1.0 bylo udržované spojení volitelným rysem a muselo být při každém požadavku znovu požadováno a potvrzováno, u protokolu http verze 1.1 je implicitní a naopak musí být explicitně signalizováno ukončení spojení. Rozdíl si ukážeme na příkladu přenosu dokumentu a vloženého obrázku. První příklad je pro protokol http verze 1.0 s udržovaným spojením. Klient, který požaduje trvalé spojení se serverem, musí zaslat v požadavku hlavičku Connection s hodnotou keep-alive:

Pokud server odpoví hlavičkou Keep-Alive, může klient zaslat další požadavek po stejném spojení. Hodnota parametru timeout určuje, jak dlouho bude spojení udržováno, pokud klient nezašle do té doby další požadavek. Hodnota max je maximální počet požadavků, kolik může klient v rámci udržovaného spojení zaslat. Požadavek na udržení spojení musí být opakován při každém dalším požadavku. Pokud některý požadavek klienta hlavičku Connection neobsahuje, server uzavře spojení po odeslání odpovědi.

Zatímco u udržovaného spojení protokolu http verze 1.0 musel klient vyčkat s dalším požadavkem až do odpovědi serveru na předcházející požadavek, protože do té doby nevěděl, zda server udržované spojení povolí, u protokolu verze 1.1 mohou být požadavky i odpovědi odesílány bez čekání na dokončení předchozího požadavku nebo odpovědi (pipelining). Díky tomu může klient vyslat požadavky na všechny vložené obrázky v jednom paketu a stejně tak server může shromáždit krátké odpovědi do několika málo delších paketů. První měření a testy ukazují, že tak lze uspořit oproti protokolu http verze 1.0 až 90 % paketů putujících po síti mezi klientem a serverem:

U prvního požadavku musí klient vyčkat, až dostane od serveru první stavový řádek, ze kterého pozná, že server komunikuje protokolem http verze 1.1. Pak už může posílat další požadavky asynchronně, bez čekání na odpověď na předchozí požadavky. Pokud klient i server zvládají protokol verze 1.1, je spojení mezi klientem a serverem udržováno až do vypršení časového limitu nebo do explicitního uzavření. Explicitní uzavření je signalizováno hlavičkou Connection.

Virtuální WWW servery

Zatímco minimální požadavek protokolu http verze 1.0 mohl být tvořen prvním řádkem požadavku bez dalších hlaviček, požadavek protokolu http verze 1.1 musí obsahovat vždy novou hlavičku Host. Tato hlavička musí obsahovat jméno serveru zadané na straně klienta. Díky této hlavičce pak může jeden server obsluhovat na jedné síťové adrese několik různých virtuálních WWW serverů. Podle hlavičky Host vždy rozezná, pro který virtuální server je požadavek určen. V protokolu http verze 1.0 musel mít WWW server tolik síťových adres, kolik virtuálních WWW serverů obsluhoval, což jen přispívalo k rychlejšímu zaplnění omezeného adresového prostoru stávajícího Internetu.

Přenos dokumentů o neznámé délce

Všechny požadavky a odpovědi protokolu verze 1.1, které obsahují data, musí deklarovat v hlavičce Content-Length skutečnou délku zasílaných dat. Při komunikaci protokolem http verze 1.0 mohl klient rozpoznat konec dat podle toho, že server uzavřel spojení. U udržovaného spojení však nemůže klient rozpoznat konec odpovědi jinak, než z deklarované délky dat. Je jasné, že oznámení správné délky dat před zahájením přenosu bude činit v některých případech problémy. Například u CGI skriptů, které generují dynamická data, není obvykle délka dat dopředu známa. Pro přenos dokumentů o neznámé délce byla proto doplněna metoda přenosu po kouscích (chunked). Výstup CGI skriptu není odesílán klientovi přímo znak po znaku, tak jak je CGI skript generuje, ale je přesměrován pomocí roury do WWW serveru. WWW server odesílá data klientovi, ale minimálně po blocích daných velikostí výstupní vyrovnávací paměti. Délky jednotlivých částí jsou známy v okamžiku, kdy začíná jejich přenos. Není proto problémem výstup CGI skriptu o neznámé délce odeslat po několika částech, jejichž délka je známa. Přenos dokumentů po částech signalizuje server hlavičkou Transfer-Encoding: chunked. Každá část o známé délce začíná hexadecimálně zapsanou délkou části, za kterou následuje její obsah:
HTTP/1.1 200 OK<CR><LF>
Transfer-Encoding: chunked<CR><LF>
<CR><LF>
1A4C<CR><LF>		délka 1. části hexadecimálně
text				obsah 1. části
...
<CR><LF>			konec 1. části
2F8<CR><LF>		délka 2. části
text				obsah 2. části
...
<CR><LF>			konec 2. části
0<CR><LF>			prázdná poslední část (konec)
Content-MD5: 9c9e5132e291fea3fd4cebb6c2e64f9a<CR><LF>
<CR><LF>
Část je ukončena prázdným řádkem. Po něm může následovat další část uvozená délkou nebo prázdná poslední část s délkou 0. Za poslední částí dokumentu mohou následovat některé dodatečné hlavičky. Například charakteristika dokumentu může být počítána algoritmem MD5 průběžně a uvedena až na konci odpovědi.

Výběr varianty dokumentu na straně serveru

Dokumenty mohou být v systému WWW uloženy v různých jazykových a kódových mutacích. Výběr mutace dokumentu na straně serveru umožňuje automaticky prezentovat dokument v tom formátu a v té jazykové variantě, kterou požaduje klient. Automatický výběr pracuje tak, že klient sdělí serveru typ dokumentu, který mu vyhovuje, a server vybere, která z dostupných variant nejlépe odpovídá požadavkům klienta. Použití automatického výběru si nejprve předvedeme na příkladu výběru varianty dokumentu podle jazyka. Většina serverů dovoluje definovat různé přípony jmen souborů, které identifikují jazyk dokumentu. Například u serverů NCSA, CERN a Apache označíme všechny soubory s příponou `czech' za české dokumenty a s příponou `eng' za anglické takto:
AddLanguage cs czech   # cs je identifikátor jazyka
AddLanguage en eng     # czech je přípona souboru
Klient může požádat o konkrétní jazykovou mutaci dokumentu explicitně, doplněním postfixu jména souboru do URL (např. index.html.czech), ale jak lze vidět z uvedené konfigurace, tento postfix nemusí odpovídat oficiální identifikaci jazyka. Většinou se sice volí přípona souborů stejná jako identifikátor jazyka, ale nemusí to být pravidlem. Podstatně pohodlnější je pro uživatele implicitní volba jazyka, nastavením preferencí v prohlížeči. Prohlížeč pak přidává do požadavků hlavičku Accept-Language, ve které sděluje serveru preferovaný jazyk. V tomto případě ovšem musí sever vyhledat vhodnou jazykovou mutaci dokumentu sám, protože zadané URL (např. index.html) neidentifikuje přímo soubor na serveru. Hledání vhodné varianty dokumentu podle preferencí prohlížeče musí být samozřejmě na straně serveru podporováno a povoleno. Například u serveru Apache musí být pro patřičný adresářový podstrom povolen parametr MultiViews:
<Directory /WWW/root>
Options Includes ExecCGI MultiViews
</Directory /WWW/root>
Pokud server dostane požadavek na URL http://server/index.html a v odpovídajícím adresáři existují pouze soubory index.html.czech a index.html.eng, zvolí jeden z nich podle preferovaného jazyka. Pokud požadavek neobsahuje hlavičku Accept-Language, pak server vybere jazykovou mutaci dokumentu dle pevně nastavené priority jazyků.

Výběr mutace dokumentů nebyl v protokolu http verze 1.0 formálně definován. Odpovídající hlavičky sice jako volitelné definovány byly, ale jejich zpracování ne. Protokol http verze 1.1 již výběr variant dokumentů definuje a to na základě požadavků klienta na:

Prohlížeč zasílá preference různých variant dokumentů při každém požadavku v hlavičkách požadavku. Prohlížeč může jednotlivým variantám přiřadit váhy v intervalu 0 až 1.0. Čím větší je hodnota váhy, tím více je preferována odpovídající varianta. Při interpretaci zápisu preferencí je třeba dát pozor na to, že oddělovačem variant je čárka, zatímco středník je oddělovačem parametrů v rámci jedné varianty. Váha varianty je zadána parametrem q:
GET /index HTTP/1.1
Accept: text/html, text/plain;q=0.2, audio/*;q=0.2;mxb=100000
Accept-Charset: ISO-8859-2, unicode-1-1
Accept-Language: cs, sk, en;q=0.9, de;q=0.5
Pokud není váha uvedena, je uvažována váha 1. V tomto příkladu tedy klient požaduje dokument ve formátu "text/html" s vahou 1.0, ve formátu "text/plain" s vahou 0,2 nebo formátu "audio/*" s vahou 0,2 a maximální velikostí 100000 slabik. Při výběru dostupné varianty dokumentu server vyhledá všechny akceptovatelné varianty, vypočte jejich váhy jako součin jednotlivých vah preferencí klienta a zašle dokument s nejvyšší výslednou vahou. Pokud dokument ve zvolené variantě přesáhne limit velikosti, zvolí se následující vyhovující varianta. Priorita preferencí se stejnými vahami postupuje zleva doprava. Pokud je k dispozici více variant požadovaného dokumentu, obsahuje odpověď navíc hlavičku Vary:
Content-Type: text/html; charset=ISO-8859-2
Content-Language: cs
Content-Length: 1241
Vary: accept-language, accept-charset
...
Hlavička Vary slouží jako pomocná informace pro ukládání dokumentů v proxy cache serverech. Proxy cache server musí ukládat dokumenty existující ve více variantách společně se všemi odpovídajícími hlavičkami Accept-*, které použil pro jejich získání a které jsou uvedeny v hlavičce Vary. V daném příkladu si musí zapamatovat použité hlavičky Accept-Language a Accept-Charset. Takto uložený dokument může poskytnout klientovi pouze tehdy, pokud klient zadal stejné nebo ekvivalentní preference v těchto hlavičkách. Na hodnotě ostatních hlaviček Accept-* neuvedených v hlavičce Vary nezáleží, protože nemají vliv na výběr varianty požadovaného dokumentu.

Hledání dostupných variant dokumentů je řešeno na straně serveru buď vyhledáním všech souborů se stejným začátkem jména bez přípony (index.*) nebo z popisného souboru variant. V prvním případě jsou atributy dokumentů určeny příponami jmen existujících souborů. Například přípona .html znamená, že soubor je typu "text/html", přípona "czech", že je v jazyce českém, apod. V druhém případě jsou jména souborů a jejich atributy dány definicemi v popisném souboru:

# popisný soubor index.var
URI: english.html			# jméno souboru
Content-Language: en			# jazyk
Content-Type: text/html; charset=ISO-8859-1  # typ MIME

URI: czech.html
Content-Language: cs
Content-Type: text/html; charset=ISO-8859-2
V popisném souboru jsou popsány všechny dostupné varianty jednoho dokumentu. Server pozná, že má použít pro dané URL popisný soubor variant podle toho, že existuje soubor se stejným jménem jako v URL a příponou danou konfigurací serveru (obvykle .var).

Při výběru mutace dokumentů se může stát, že žádná z dostupných variant není pro klienta přijatelná. V tomto případě server může odpovědět chybovým kódem 406 (NOT ACCEPTABLE) a nabídnout dostupné varianty dokumentu:

HTTP/1.1 406 Not Acceptable
Server: Apache/1.2b8 dev
Vary: accept-language
Connection: close
Content-type: text/html

<HTML><HEAD>
<TITLE>406 Not Acceptable</TITLE>
</HEAD><BODY>
<H1>Not Acceptable</H1>
An appropriate representation of the requested resource / could not be found on this server.<P>
Available variants:
<ul>
<li><a href="index.html.czech">index.html.czech</a>, type text/html, language cs
<li><a href="index.html.eng">index.html.eng</a>, type text/html, language en
</ul>
</BODY></HTML>
Výběr varianty dokumentu na straně serveru byl sice definován až v protokolu http verze 1.1, ale je již delší dobu v mnoha serverech implementován a používán. Přitom se začínají postupně objevovat nevýhody této koncepce. Především popis přijatelných mutací dokumentu je u inteligentních prohlížečů poměrně složitý a dlouhý, takže by v plném tvaru podstatně prodlužoval každý požadavek. Naopak dokumenty obvykle nejsou dostupné ve všech možných mutacích, ale pouze v několika málo, například ve formátu text/html a application/pdf.. Proto klient posílá v hlavičkách Accept pouze omezenou podmnožinu svých schopností a volba mutace na straně serveru nemůže být díky tomu optimální. Proxy cache servery navíc musí ukládat dokumenty v různých variantách podle různých použitých preferencí klientů, přičemž nemohou zjistit, zda různé preference nevedou na stejnou variantu dokumentu. Obvykle je počet dostupných mutací dokumentu podstatně menší, než výčet mutací, které akceptuje klient. V protokolu http verze 1.1 je proto uvedena možnost přenést výběr varianty dokumentů na stranu klienta. Konkrétní realizace je pak předmětem připravovaného standardu Transparent Content Negotiation.

Přenos části dokumentu

Při komunikaci se serverem se často stává, že přenos je přerušen. Pokud se jedná o krátký dokument, není to žádná tragédie, stačí opakovat požadavek a přenést dokument znovu. U dlouhých dokumentů to je velmi nepříjemné a může se stát, že se ani opakovaně nepodaří přenést celý dokument najednou. Je to podobný problém, jako u programu ftp, kde byl vyřešen zavedením příkazu reget, který umožňuje pokračovat v přerušeném přenosu. V protokolu http verze 1.1 byl tento problém vyřešen zavedením požadavku na přenos části dokumentu. Protože server systému WWW nemusí být vždy schopen zaslat stejný dokument opakovaně, například pokud je dokument dynamicky generován, musí signalizovat možnost opakování části přenosu hlavičkou Accept-Ranges. Pokud odpověď serveru obsahuje tuto hlavičku, může klient při neúspěšném přenosu zopakovat požadavek a požádat o část dokumentu hlavičkou Range:
GET /doc/VeryLongDocument.html HTTP/1.1
Range: 1000-8000,50000-
Požadovaná část je určena intervalem od počáteční po poslední požadovanou slabiku dokumentu. Pokud není uvedena horní mez, je přenesen dokument až do konce. Pokud není uvedena dolní mez, je přenesen zadaný počet slabik od konce dokumentu. V jedné hlavičce může být uvedeno více intervalů, oddělených čárkami. Pokud klient požaduje několik částí, zašle je server ve tvaru zprávy o více částech ve formátu MIME. Každá část navíc obsahuje hlavičku Content-Range, která identifikuje obsažený interval:
Content-Type: multipart/x-byteranges; boundary=MARK

--MARK
Content-Type: text/html
Content-Range: 1000-8000/327482

...
--MARK
Content-Type: text/html
Content-Range: 50000-327482/327482

...
--MARK

Přechod na nový protokol

Přechod na nový protokol nebude zcela bezbolestný. Přestože se původně zdálo, že podle verze protokolu v požadavku a odpovědi budou schopni jak server, tak klient rozlišit, s jakým protějškem komunikují, v praxi se ukázalo, že je celá řada špatně napsaných programů, které se s vyšším číslem subverze protokolu nevyrovnají.

Další materiály:


Poslední změna:
Pokud máte námět na vylepšení této stránky nebo na ní naleznete chybu, zašlete dopis na adresu lampa@fit.vutbr.cz.