HTML v příkladech

8

Common gateway Interface (CGI)

 
Obsah

Rejstřík

Hledat

Dopis autorovi

...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.

Common Gateway Interface

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.

Výstup

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í.

Vstup

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 prakticky

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.


Pavel Satrapa
Článek byl otištěn v časopise
Softwarové noviny číslo 3/97
 
<--- --->