...příklad pro osmou část...
V našem seriálu jsme se dosud věnovali pouze statickým stránkám. Ty jsou
uloženy v podobě souborů kdesi na disku. Když WWW server obdrží dotaz, hmátne
po příslušném souboru a odešle jej klientovi. CGI umožňuje, aby server na
základě dotazu spustil program a jako odpověď odeslal výsledky jeho práce.
Dovoluje tedy začlenit do WWW programy a stránky konstruovat za běhu podle
momentální situace a požadavků uživatele.

Slůvko "Interface" jasně naznačuje, že CGI je definicí rozhraní. Jedná se o
rozhraní mezi WWW serverem a spouštěným programem. Popisuje, jakým způsobem
server předá programu informace o dotazu, který jej vyvolal, a jak převezme
odpověď k odeslání klientovi.
Základní pravidla CGI jsou dosti jednoduchá. Celá transakce začíná příchodem
dotazu, požadujícího spuštění programu. Jak jej server odliší od dotazů
"obyčejných" závisí na jeho konfiguraci. Zpravidla lze nařídit, že soubory z
jistého adresáře (nejčastěji /cgi-bin) nebo s jistou příponou
(.cgi) mají být chápány jako CGI programy a podle toho jest s nimi
zacházeti.
Než server odstartuje program, připraví pro něj informace o dotazu, který jej
vyvolal. Uloží je do sady proměnných prostředí, jejichž jména jsou předepsána
ve specifikaci CGI. Poté spustí vlastní program. Ten zpracuje poskytnuté
informace a na jejich základě vyrobí jakýsi výstup. Nejčastěji HTTP dokument,
ale může se jednat o obrázek či jakýkoli jiný druh informací, přepravitelných
prostřednictvím WWW. Ke svému výsledku přibalí hlavičky protokolu HTTP (budeme
se mu věnovat v příštím dílu) a vše odešle do svého standardního výstupu. Tam na
ně čeká WWW server, který je odešle jako odpověď na klientův dotaz.
Pro spouštěný program je toto schéma velmi přátelské, protože zcela obchází
komunikační záležitosti. On prostě přijme v proměnných prostředí a případně ve
standardním vstupu jakési údaje a do standardního výstupu zapíše svůj výsledek.
Nemusí jej trápit komunikace s klientem, překonávání výpadků sítě, autorizace
či šifrování přenášených dat. To vše za něj obstará WWW server.
Podívejme se nyní podrobněji na jednotlivé části CGI.

Začneme šťastným koncem, protože výstup informací je nejjednodušší složkou
definice CGI. Jak již bylo řečeno, program své výsledky píše do standardního
výstupu. Důležité je, že tyto výsledky musí mít dvě části: HTTP hlavičky a za
nimi vlastní data. Navzájem jsou tyto části odděleny prázdným řádkem.
Primitivní CGI program v jazyce Perl by mohl vypadat nějak takto
#! /usr/local/bin/perl
print "Content-Type: text/html\n";
print "\n";
print "Jsem tady a pracuji!\n";
Vyrobí třířádkový textový výstup. První řádek obsahuje HTTP hlavičku s
oznámením, že následuje stránka v jazyce HTML. Po něm program vytvoří prázdný
řádek pro ukončení hlaviček a na závěr pak vlastní tělo. Krátkou poznámku
zaslouží ještě první řádek vlastního programu. Je určen pro prostředí
operačního systému Unix. V něm zařídí, že dotyčný program bude zpracován
interpretem jazyka Perl.
Takto vyrobený program umístíte do adresáře, ze kterého WWW server startuje CGI
programy a který má URL /cgi-bin. Řekněme, že bude jmenovat
hello. Když pak WWW klient požádá server o URL
/cgi-bin/hello, obdrží obrazovku s nápisem "Jsem tady a pracuji!".
Možná se ptáte, proč jsme zvolili zrovna Perl. Skutečností je, že z pohledu
teorie programovacích jazyků je Perl jednou z největších příšerností, které kdy
byly stvořeny. Ovšem nahlíženo čistě pragmaticky se jedná o velmi cenný
nástroj. Především jako jediný z běžně rozšířených jazyků kombinuje regulární
výrazy s běžnými programátorskými konstrukcemi, jako je podmíněný příkaz, cykly
a podobně. To z něj činí neskutečně silný nástroj především při práci s texty.
Druhou vážnou předností je, že interpret Perlu dnes existuje pro všechny běžně
rozšířené operační systémy. V době vzniku této části kolega Kolář chystal
článek, který vás s tímto jazykem seznámí.

Informace o "svém" dotazu obdrží CGI program ve skupině proměnných prostředí.
Definice CGI jich zavádí kolem dvaceti a některé WWW servery přidávají své
vlastní. Ty nejdůležitější a nejčastěji používané najdete v tabulce 1. Kromě
nich se program dozví verze použitých protokolů a programů, adresy serveru i
klienta či způsob autorizace. Ty však ponecháme stranou.
Tabulka 1: Proměnné prostředí pro CGI
REQUEST_METHOD |
kterou HTTP metodu použil klient pro dotaz |
QUERY_STRING |
klientův dotaz (při metodě GET) |
CONTENT_LENGTH |
délka těla dotazu (při metodě POST) |
CONTENT_TYPE |
typ informací v těle dotazu (při metodě POST) |
PATH_INFO |
cesta z URL, kterou má program zpracovat |
PATH_TRANSLATED |
tatáž cesta, avšak převedená na cestu ve zdejším
systému souborů |
SCRIPT_NAME |
URL vlastního programu |
|
Perl nabízí pro přístup k proměnným prostředí asociativní pole ENV.
Hodnotu proměnné PATH_INFO tedy lze získat konstrukcí
$ENV{"PATH_INFO"}.
Nejzajímavější jsou ve většině případů data, odeslaná klientem (a potažmo
jeho uživatelem). V nich lze předat hledaný řetězec, údaje z registračního
formuláře, dopis správci a podobně. Protokol HTTP nabízí dvě metody pro jejich
dopravu.
Jednodušší a častěji používaná je metoda GET. Při ní se odesílané informace
stávají součástí URL. Za cestu, identifikující spouštěný program, se připojí
otazník a za něj pak příslušný řetězec znaků. Například URL
http://www.kdesi.cz/cgi-bin/test?Nazdar
požaduje, aby server spustil CGI program test a jako data od uživatele
mu předal řetězec Nazdar. Že byly informace předány tímto způsobem
pozná program podle toho, že proměnná prostředí REQUEST_METHOD má
hodnotu GET. Vlastní data tvoří obsah proměnné QUERY_STRING.
Kromě toho je server má předat programu i ve formě parametrů při volání
programu. Doporučuje se však spoléhat raději na QUERY_STRING.
Objem informací, které lze předávat metodou GET, je značně omezen. Můžete
počítat s maximální délkou kolem 200 bajtů. Druhou nepříjemností je, že
informace se objeví v URL a tím pádem i v protokolu o činnosti serveru. Pokud
se jedná o důvěrné údaje, jejich autor nebude příliš potěšen.
Metoda POST odstraňuje oba citované nedostatky. Při ní jsou informace odesílány
v těle dotazu, položeného klientem. Proměnná prostředí REQUEST_METHOD
má v tomto případě hodnotu POST a program obdrží informace ve svém
standardním vstupu. Proměnná CONTENT_LENGTH mu sdělí jejich délku (v
bajtech) a CONTENT_TYPE jakého druhu (obrázek, text, HTML stránka...)
jsou. Podle definice CGI nesmí program přečíst ze vstupu více než
CONTENT_LENGTH bajtů. Toto omezení může poněkud zkomplikovat výrobu
CGI programů v některých jazycích. V Perlu lze použít příkaz
read ( STDIN, $data, $ENV{"CONTENT_LENGTH"} );
který do proměnné $data načte celý vstup.
Aby pozice programátora byla ještě o něco složitější, jsou data zakódována.
Jedná se o tak zvané URL kódování, jehož cílem je umožnit používání speciálních
znaků v lokátorech. Mezera se nahrazuje znakem "+", ostatní speciální znaky
(např. plus, procento či znaky z horní poloviny ASCII kódu) se přemění na
trojici %XX, kde XX je kód dotyčného znaku v šestnáctkové soustavě. Například
Otec + syn se v URL kódování změní na Otec+%2B+syn.
Je evidentní, že metoda GET, která přepravuje data v lokátoru, musí používat
URL kódování. Stejným způsobem je však zakódováno i tělo dotazu při metodě
POST. Abyste se dostali k původnímu znění, je třeba text v každém případě
dekódovat. V Perlu poslouží dvojice příkazů
s/\+/ /g
s/%(..)/pack("c",hex($1))/ge
První se postará o mezery, druhý o trojice %XX. Je velmi záhodno podrobit
následně data bezpečnostní prověrce. CGI programy totiž představují
nezanedbatelné riziko z hlediska bezpečnosti počítače, na kterém jsou
provozovány. Běžným druhem útoku je pokusit se vnutit programu nějaké speciální
znaky, které způsobí spuštění úplně jiného programu, než zamýšlel autor. Proto
doporučujeme prověřit, zda uživatel zadal pouze přípustná data.
Existují dva způsoby, jak se zachovat při výskytu nepovolaných znaků.
Konzervativní přístup předepisuje okamžitě vytvořit stránku s chybovým hlášením
a ukončit CGI program. Chcete-li být liberální, vypusťte neposlušné znaky a
zbytek zpracujte, jako by se nic nestalo. Lze použít třeba následující příkaz,
který vypustí vše kromě písmen anglické abecedy, číslic a podtržítka
s/\W//g

CGI programy našly v současném Internetu celou řadu aplikací. Mezi nejčastější
patří počítání návštěvníků stránky, změna kódování češtiny, přístupy k
databázím a podobně. Při těchto aplikacích však zpravidla budete používat
hotové produkty. Pustíte-li se sami do programování CGI, půjde nejspíš o
zpracování dat z formuláře.
Pro tento účel bylo vyvinuto několik podpůrných knihoven. Na URL http://hoohoo.ncsa.uiuc.edu/cgi/forms.html najdete některé z nich.Nejsou určeny pouze pro Perl, ale i pro jiné jazyky, používané k vytváření CGI
programů. Ve světě Perlu je nejznámějším produktem této kategorie
cgi-lib
(http://www.bio.cam.ac.uk/cgi-lib/). Základní funkcí, kterou
knihovna poskytuje, je ReadParse. Ta obstará kompletní vstup dat z
formuláře. Zjistí si, zda byla předána metodou GET nebo POST, načte je a uloží
do asociativního pole in, v němž jako klíče slouží názvy polí z
formuláře. Například pro formulář z minulé části seriálu bychom po provedení
ReadParse získali jméno uživatele pomocí $in{"jmeno"}.
Jestliže několik polí nese stejné jméno (například sada vypínačů "mame" v našem
formuláři), jsou všechny jejich hodnoty uloženy do jedné buňky pole in
pod svým společným jménem. Navzájem jsou odděleny znakem s kódem nula (\0).
Na závěr dnešní části se podívejme na náš příklad. Je to jednoduchý program se
jménem cgivars, který používám při ladění CGI. Má jedinou funkci:
popíše kompletní prostředí, ve kterém pracuje. Vypíše hodnoty všech proměnných
prostředí (skutečně všech, nejen těch, které jsou součástí CGI) a pokud dostává
data metodou POST, přidá i obsah standardního vstupu.
Program používám dvěma způsoby. Především se lze jeho prostřednictvím
přesvědčit, jak vlastně vypadají informace, vstupující do CGI programu. Lze
snadno posoudit, zda případný problém je v programu nebo v tom, že do něj
vstupují jiná data, než jste předpokládali. Pokud je skutečně chyba v programu
(což je bohužel častější případ), lze výsledky využít k simulaci CGI prostředí.
Nepříjemnost ladění CGI programů spočívá v tom, že programátor nemá přístup k
výsledkům programu. Neodpovídá-li výstup pravidlům CGI, WWW server místo něj
odešle zprávu "skript nevydal korektní odpověď". Vy však můžete CGI rozhraní
svému programu úspěšně předstírat. Stačí, když mu v dávkovém souboru nastavíte
proměnné prostředí přesně tak, jak je ohlásil cgivars, a poté program spustíte.
Nyní bude své výsledky psát přímo na obrazovku a vy uvidíte, co ze sebe vydal a
proč s tím server nesouhlasil. Přiložený obrázek uvádí výsledky programu
cgivars pro mnou vyplněný formulář z minulé části.
|