CGI-skripty

Jiří Kosek ml.

Dosud jsme se zabývali případy, kdy určité URL adrese odpovídal na serveru soubor, který obsahoval HTML-kód doplněný případně o nějaké výkonné příkazy (SSI, ASP, PHP), které se před odesláním dokumentu provedly. URL však může ukazovat přímo na spustitelný soubor, který po svém spuštění vygeneruje HTML stránku. Spustitelnému souboru říkáme obvykle CGI-skript, podle rozhraní CGI (Common Gateway Interface), které definuje způsob předávání dat mezi WWW-serverem a CGI-skriptem.

Jaké jazyky můžeme použít pro psaní CGI-skriptů?

Odpověď je jednoduchá -- pro psaní CGI-skriptů můžeme použít téměř libovolný programovací jazyk. Nejčastěji se používají různé příkazové interprety Unixu a jazyk Perl. Poměrně často se CGI-skripty píší i v jazycích C nebo C++. Takto napsané skripty bývají rychlejší, mají menší systémové nároky a navíc jsou bezpečnější. Největší novinkou na poli jazyků pro CGI je však Java. V Javě lze kromě apletů psát i běžné aplikace a ty mohou plnit funkci CGI-skriptu. Jako analogie k názvu aplet se těmto programům někdy říká servlety -- CGI skripty jsou samozřejmě vždy prováděny na serveru.

Aby byl výsledný program použitelný jako CGI-skript, musí splňovat pouze dvě podmínky:

Jak probíhá spolupráce WWW-serveru s CGI-skriptem?

Na počátku komunikace je opět požadavek klienta na určité URL. Toto URL však nyní ukazuje na CGI-skript. Kromě adresy CGI-skriptu může klient předat serveru parametry, které ovlivní chování CGI-skriptu.

Server zjistí, že požadované URL je potřeba obsloužit CGI-skriptem. Server to nejčastěji pozná podle toho, že na začátku cesty v URL je uveden adresář cgi-bin. (Jméno tohoto adresáře lze nastavit v serveru Apache pomocí direktivy ScriptAlias v konfiguračním souboru srm.conf). Server skript spustí a předá mu parametry pomocí rozhraní CGI.

Nyní hlavní slovo dostává CGI-skript. Zpracuje předané parametry a jako výsledek na svůj standardní výstup zapíše odpověď ve tvaru protokolu HTTP. Tento výstup je zachycen WWW-serverem, který doplní další hlavičky do HTTP odpovědi a vše pošle zpět klientovi jako odpověď. (V této fázi se WWW-server obvykle chová poněkud protřele a stará se o to, aby odpověď byla zaslána stejnou verzí HTTP jakou použil požadavek. Pokud tedy byl požadavek vznesen pomocí HTTP/0.9, odstraní WWW-server před odesláním výstupu CGI-skriptu všechny HTTP hlavičky.)

Obr. 1: Obsloužení požadavku CGI-skriptem
Obsloužení požadavku CGI-skriptem

Náš první CGI-skript

Než se pustíme do psaní vlastních CGI-skriptů, měli bychom si ověřit, zda to máme od správce serveru vůbec povoleno. Servery bývají často nakonfigurovány tak, že CGI-skripty lze spouštět pouze z jednoho adresáře a do tohoto adresáře nemá právo přístupu každý. Pouze ti uživatelé, o kterých si správce serveru myslí, že jejich skripty nenaruší bezpečnost serveru.

Pokud máme vytváření CGI-skriptů povoleno, musíme si rovněž zjistit, do kterého adresáře je můžeme ukládat. Obvykle bývá vyhrazen jeden společný adresář (a jeho podadresáře) pro všechny uživatele. Na Unixu tento adresář bývá např. /usr/local/etc/httpd/cgi-bin, ve Windows instalaci serveru Apache pak x:\Apache\cgi-bin. Pokud do tohoto adresáře uložíme skript pojmenovaný pokus.cgi, bude přístupný pomocí URL http://server/cgi-bin/pokus.cgi.

Nyní jsou zdánlivě všechny problémy vyřešeny. Opak je však pravdou. Nyní nám zbývá vybrat programovací jazyk, ve kterém budeme CGI-skripty psát. Pravděpodobně si vybereme ten jazyk, který dobře ovládáme. Pro zápis našeho ukázkového skriptu použiji příkazový interpret sh, který je nedílnou součástí všech instalací operačního systému Unix. Skripty pro sh jsou obdobou dávkových souborů, jak je známe ještě z dob MS-DOSu. Naše ukázka však bude tak jednoduchá, že ji pochopíte i bez znalosti interpretu sh.

Vytvoříme skript, který vypíše seznam uživatelů, kteří právě na serveru pracují. (V Unixu totiž může na jednom počítači pracovat více uživatelů najednou.) K výpisu právě přihlášených uživatelů slouží příkaz who. Ten budeme proto volat z našeho skriptu, který kromě toho vytvoří potřebné hlavičky HTTP. V praxi většinou stačí použít pouze hlavičku Content-type a určit typ dat, která dále bude skript generovat. Jelikož příkaz who generuje obyčejný textový výstup, můžeme použít typ dat text/plain -- obyčejný text. Skript uložíme např. do souboru test1.cgi.

#!/bin/sh
echo 'Content-type: text/plain'
echo 
/usr/bin/who
Skript je poměrně krátký, my se na něj podíváme trošku podrobněji a vše si vysvětlíme. První, poněkud magická, řádka skriptu určuje, který příkazový interpret se použije pro vykonání skriptu -- v našem případě tedy sh, který je uložen v adresáři bin.

Příkaz echo vypisuje svůj argument na standardní výstup. Druhá a třetí řádka CGI-skriptu tedy vygeneruje HTTP hlavičku (typ dat a prázdná řádka). Čtvrtý řádek zavolá přímo příkaz who. Výstup příkazu je zaslán na standardní výstup a proto se už o nic nemusíme starat.

U souboru test1.cgi musíme ještě správně nastavit atributy tak, aby byl soubor spustitelný. K tomu nám poslouží příkaz chmod +x test1.cgi.

Výsledek našeho snažení si můžeme prohlédnout na obrázku 2. Funguje to, ale jaksi to není ono. Výstup je příliš strohý a zdaleka nevyužívá možnosti, které nám Web nabízí.

Obr. 2: Výstup našeho prvního CGI-skriptu
Výstup CGI-skriptu test1.cgi

Využijeme toho, že CGI-skript může klidně generovat HTML-kód. Stačí, když v HTTP hlavičce použijeme Content-type: text/html a výstup skriptu se bude v prohlížeči interpretovat jako stránka zapsaná HTML. Upravíme tedy náš skript do nové podoby a pojmenujeme jej např. test2.cgi (opět nesmíme zapomenout na nastavení atributu spustitelnosti):

#!/bin/sh
echo 'Content-type: text/html'
echo
echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">'
echo '<HTML>'
echo '<TITLE>Přihlášení uživatelé</TITLE>'
echo '</HEAD>'
echo '<BODY>'
echo '<H1>Přihlášení uživatelé</H1>'
echo '<PRE>'
/usr/bin/who
echo '</PRE>'
echo 'V případě problémů a dotazů kontaktuj'
echo '<A HREF="mailto:webmaster@server.cz">Webmastera</A>.'
echo '</BODY>'
echo '</HTML>'
Pomocí příkazů echo jsme vygenerovali všechen potřebný HTML-kód. Výstup programu who jsme umístili mezi tagy <PRE> a </PRE>, aby bylo zachováno řádkovaní. Výsledek nového skriptu je již mnohem uspokojivější (obr. 3.).

Obr. 3: Výstup upraveného CGI-skriptu
Výstup CGI-skriptu test2.cgi

Po opravdu krátkém úvodu do problematiky CGI na nás v následujícím pokračování seriálu bude čekat popis předávání parametrů pomocí rozhraní CGI. Teprve poté mohou být naše skripty interaktivní a aktivně reagovat na potřeby uživatelů.

Už dnes si však může položit otázku, zda je lepší používat CGI-skripty nebo některý z moderních systémů serverových vsuvek jako PHP nebo ASP. Ve většině případů je mnohem snazší a rychlejší pro vývoj aplikací použít PHP nebo ASP. Použití klasických CGI-skriptů je výhodné v případech, kdy "toho potřebujeme hodně spočítat a málo zobrazit" -- viděli jsme, že všechen HTML-kód se v CGI-skriptech musí poměrně pracně zapisovat pomocí příkazu echo nebo nějaké jeho obdoby. Jak uvidíme příště, proti použití CGI hovoří i složitější práce s parametry a potencionálně větší bezpečnostní rizika.

© Jiří Kosek 1999