[ Pobierz całość w formacie PDF ]
Programowanie CGI w Perlu 45
Scott Guelich, Shirshir Gundavaram, Gunther Birznieks
Programowanie CGI w Perlu
Rozdział 1 Pierwsze kroki
Podobnie jak cały Internet, CGI, czyli Common Gateway Interface, przebył długą drogę w bardzo krótkim czasie. Zaledwie parę lat temu skrypty CGI były nie więcej niż gadżetem i nie znajdowały szerszego zastosowania; służyły do obsługi liczników odwiedzin oraz prowadzenia książek gości, a przy tym pisali je głównie hobbiści. Obecnie skrypty CGI, pisane przez profesjonalnych twórców środowisk webowych, wyposażają w logikę, tchnącą życie w niezwykle rozległą strukturę, jaką stał się Internet.
Historia
Internet nie jest nowością, choć dopiero obecnie poświęca mu się dużo uwagi. W rzeczywistości sieć będąca poprzedniczką dzisiejszego Internetu swymi korzeniami sięga trzydziestu lat wstecz. Internet narodził się jako ARPAnet - sieć założona przez Departament Obrony Stanów Zjednoczonych w celu prowadzenia badań nad sieciami komputerowymi. Przez pierwsze 25 lat Internet rozrastał się stopniowo, aż w końcu nastąpił jego zdumiewający rozkwit.
Na Internet zawsze składały się rozmaite protokoły wymiany informacji, lecz pojawienie się przeglądarek Web, takich jak NCSA Mosaic, a później Netscape Naviga-tor, dało impuls do wręcz skokowego rozrostu. W ciągu ostatnich sześciu lat liczba hostów wzrosła od mniej niż tysiąca do ponad dziesięciu milionów. Obecnie Internet najczęściej kojarzony jest z siecią Web. Inne protokoły, na przykład obsługujące pocztę elektroniczną (ang. e-mail), FTP, pogawędki (ang. chat) i grupy dyskusyjne (ang. newsgroups), niewątpliwie stale się cieszą popularnością, jednak pierwsze miejsce zajmuje Web, gdyż coraz więcej ludzi korzysta z serwisów webowych jako bram, przez które sięgają do pozostałych, wcześniej wymienionych usług.
Sieć Web była bez wątpienia pierwszym rozwiązaniem technicznym umożliwiającym publikowanie i wymianę informacji, jednak w sieci Web było coś jeszcze, co wyzwoliło jej prawdziwą eksplozję. Pragnęlibyśmy powiedzieć, że to interfejs CGI był jedynym czynnikiem, który we wczesnym okresie przyczynił się do tego, że sieć Web swym zasięgiem przerosła takie protokoły, jak FTP i Gopher. Nie byłaby to jednak prawda. Prawdopodobnie faktyczną przyczyną zdobycia przez Web popularności była towarzysząca jej grafika. Sieć Web opracowano pod kątem prezentowania różnorodnych nośników informacji: niemal od samego początku przeglądarki obsługiwały śródtekstowe obrazki, a HTML pozwalał na elementarne kształtowanie układu strony, co ułatwiło prezentację i odbiór informacji. Możliwości wciąż się zwiększały w miarę jak Netscape rozbudowywał obsługę o nowe rozszerzenia języka HTML wraz z każdą kolejną wersją przeglądarki.
Dlatego początkowo sieć Web przybrała postać zbioru osobistych stron interneto-wych oraz garstki serwisów Web oferujących całą gamę rozmaitych informacji. Niemniej nikt nie miał tak naprawdę pomysłu, jak te zasoby wykorzystać, zwłaszcza komercyjnie. W 1995 roku w firmach zazwyczaj słyszało się: „O, tak! Internet to znakomita rzecz, ale mało komu udało się za jego pośrednictwem coś zarobić". Jakże szybko świat się zmienia.
Zastosowanie CGI dzisiaj
Wystartował handel elektroniczny (ang. e-commerce) i wszędzie można spotkać firmy z .com w adresie internetowym (tzw. dot-comy, ang. dot-coms). Niektóre rozwiązania techniczne stały się fundamentem tego postępu, a CGI jest z pewnością jednym z najważniejszych. CGI sprawia, że sieć Web nie musi być zbiorem wyłącznie statycznych zasobów, lecz może faktycznie działać. Zasoby statyczne to takie, które pozostają w stanie niezmienionym przy kolejnych żądaniach, na przykład pliki HTML lub grafika. Natomiast zasoby dynamiczne zawierają informacje, które przy każdym żądaniu mogą ulegać zmianom w zależności do warunków, na przykład zmiany w źródle danych (np. bazy danych), tożsamość użytkownika lub wprowadzane przez niego informacje. Dzięki temu, że CGI umożliwia tworzenie dynamicznych treści, serwery Web mogą dostarczać aplikacji sieciowych, dostępnych dla użytkowników na całym świecie, posługujących się różnorodnymi platformami, za pośrednictwem standardowego programu-klienta, czyli przeglądarki Web.
Trudno wyliczyć wszystkie możliwości interfejsu CGI, ponieważ lista byłaby bardzo długa. Gdy przeszukujemy serwis Web, wyszukiwaniem prawdopodobnie zajmuje się aplikacja CGI. Gdy w serwisie Web wypełniamy formularz rejestracyjny, przetwarzaniem podanej informacji prawdopodobnie zajmie się aplikacja CGI. Gdy robimy internetowe zakupy, zatwierdzeniem karty kredytowej i rejestracją transakcji prawdopodobnie zajmuje się aplikacja CGI. Gdy w sieci oglądamy wykres, na którym w sposób dynamiczny przedstawiane są informacje w formie graficznej, prawdopodobnie został on utworzony przez aplikację CGI. Oczywiście, przez kilka ostatnich lat pojawiły się inne rozwiązania techniczne zdolne obsłużyć wymienione przed chwilą dynamiczne funkcje; niektórym z nich wkrótce przyjrzymy się bliżej. Mimo to do takich realizacji nadal najczęściej wykorzystywany jest CGI.
Wprowadzenie do CGI
Wielkie możliwości CGI wynikają z jego prostoty. CGI jest interfejsem wagi lekkiej - stanowi minimum, które serwer Web powinien zapewniać, aby zewnętrzne procesy mogły tworzyć strony Web. Kiedy serwer Web otrzymuje żądanie statycznej strony Web, zwykle wyszukuje odpowiedni plik HTML w systemie plików. Gdy serwer Web otrzymuje żądanie skryptu CGI, serwer ten wykonuje skrypt CGI jako kolejny proces (tj. osobną aplikację); serwer przekazuje do procesu pewne parametry, a na jego wyjściu odbiera dane, które następnie zwraca programowi-klientowi w takiej postaci, jak gdyby pochodziły z pliku statycznego (zob. rysunek 1.1).
Jak zatem działa cały interfejs? Pozostałą część książki poświęcimy szczegółowej odpowiedzi na to pytanie, najpierw jednak zapoznajmy się z podstawami.
Żądania zasobów dynamicznych, w tym skryptów CGI, zgłaszane przez przeglądarki Web nie różnią się od żądań jakichkolwiek innych zasobów w sieci Web: przeglądarki wysyłają wiadomość sformatowaną zgodnie z protokołem transferu hipertekstu, czyli HTTP (Hypertext Transfer Protocol). Protokół HTTP omawiamy w rozdziale 2. Żądanie HTTP zawiera uniwersalny lokator zasobów, czyli URL (Unłuersal Resource Locator). Serwer Web na podstawie URL-a ustala, który zasób ma zwrócić. Zazwyczaj skrypty CGI znajdują się w jednym katalogu, na przykład /cgi, lub mają jednakowe rozszerzenie nazwy pliku, na przykład .cgi. Jeśli serwer Web rozpozna, że żądanie dotyczy skryptu CGI, wykona skrypt.
Powiedzmy, że chcielibyśmy zajrzeć pod URL http://www.mechanicymirka.com/cgi/ welcome.cgi. Najprostszy z możliwych przykład 1.1 przedstawia żądanie HTTP, które może zostać wysłane przez przeglądarkę Web.
Przykład 1.1. Przykładowe żądanie HTTPGET /cgi/welcome.cgi HTTP/1.lHost: www.mechanicymirka.com
W przedstawionym żądaniu pobrania, GET, zasób do pobrania identyfikowany jest jako /cgi/welcome.cgi. Gdy założymy, że nasz serwer wszystkie pliki w drzewie katalogu /cgi uznaje za skrypty CGI, wtedy automatycznie wykona skrypt welcome.cgi, zamiast zwrócić jego zawartość bezpośrednio do przeglądarki.
Programy CGI pobierają dane wejściowe ze standardowego wejścia (STDIN) oraz ze zmiennych środowiska. Zmienne te zawierają na przykład informacje o tożsamości zdalnego hosta i użytkownika, wartości elementów wysłane z formularza (jeśli w ogóle zostały podane) itd. Przechowywane są w nich również: nazwa serwera, protokół komunikacyjny oraz nazwa oprogramowania, na którym oparte jest działanie serwera. Każdemu z tych elementów przyjrzymy się bliżej w rozdziale 3, „CGI — wspólny interfejs bramy".
Kiedy program CGI zacznie działać, wysyła swoje dane wyjściowe z powrotem do serwera Web poprzez standardowe wyjście (STDOUT). Zrobienie tego w Perlu jest łatwe, ponieważ domyślnie wszystko, co jest drukowane*, kierowane jest do stdout. Skrypty CGI mogą generować własne dane wyjściowe i zwracać je w postaci nowego dokumentu, lecz mogą też dostarczyć kolejny URL, do którego żądanie zostanie przekazane. Wskazówką dla serwera Web jest specjalny wiersz sformatowany jako nagłówek HTTP, który drukują skrypty CGI. Nagłówkom tym przyjrzymy się w następnym rozdziale, mimo to tutaj podajemy przykład tego, co skrypt CGI zwracający HTML mógłby podać na wyjście:
Content-type: text/htmlSkrypty CGI mogą też zwracać jeszcze inne wiersze nagłówkowe, dlatego skrypt CGI, aby zasygnalizować, że zakończył wysyłanie nagłówków, drukuje pusty wiersz. Na koniec, jeśli na wyjście przekazywany jest dokument, drukowana jest także zawartość dokumentu.
Serwer Web przyjmuje produkt wyjściowy skryptu CGI i dodaje własne nagłówki HTTP przed odesłaniem go do przeglądarki użytkownika, który wystosował żądanie. Przykład 1.2 przedstawia odpowiedź, jaką przeglądarka Web mogłaby otrzymać od serwera Web.
Przykład 1.2. Przykładowa odpowiedź HTTP
HTTP/1.l 200 OKDate: Sat, 18 Mar 2000 20:35:35 GMTServer: Apache/1.3.9 (Unix)
Last-Modified: Wed, 20 May 1998 14:59:42 GMTETag: "74916-656-3562efde"Content-Length: 2000
Content-Type: text/html
<HTML>
<HEAD>
<TITLE>Zapraszamy do bazy danych Mechaników Mike'a</TITLE>
</HEAD>
<BODY BGCOLOR="łffffff">
<IMG SRC="/images/mike.jpg" ALT="Mechanicy Mike'a">
<P>Witamy w serwisie dyn34.my-isp.net! Co tu można znaleźć? Listę mechaników z całego kraju oraz rodzaj oferowanych przez nich usług — stworzoną na podstawie uwag i propozycji użytkowników.</P>
<P>Na co czekasz? Kliknij <A HREF="/cgi/lista.cgi">tutaj</A>, aby przejrzeć listę.</P>
<HR>
<P>Bieżące wskazanie czasu według serwera: Sat Mar 18 10:28:00 2000.</P>
<P>Jeśli natrafisz na jakieś problemy w naszym serwisie lub zechcesz zgłosić nam swoje propozycje, napisz do nas na adres elektroniczny <A HREF="mailto:webmaster@mechanicymikea.com"> webmaster@mechanicymikea.com</A>.
</BODY>
</HTML>
W nagłówku podawany jest protokół komunikacyjny, data i godzina odpowiedzi, nazwa i wersja serwera, data i godzina ostatniej modyfikacji dokumentu, znacznik jednostki wykorzystywany przy buforowaniu, długość odpowiedzi oraz typ nośnika dokumentu - w przytoczonym przykładzie jest to dokument tekstowy z formatowaniem HTML. Takie nagłówki włączane są do wszystkich odpowiedzi zwracanych przez serwery Web. Nagłówkom HTTP przyjrzymy się bliżej w następnym rozdziale. Jednak już teraz zapamiętajmy, że nie ma tu niczego, co by umożliwiało odróżnienie w przeglądarce, czy odpowiedź ta oparta jest na statycznym pliku HTML, czy też została wygenerowana dynamicznie przez skrypt CGI. Jest tak, jak być powinno: przeglądarka zwróciła się do serwera Web o zasób i otrzymała zasób. Nie jest dla niej ważne, skąd pochodzi dokument ani jak go serwer wygenerował.
CGI umożliwia generowanie danych wyjściowych, które z punktu widzenia końcowego użytkownika nie różnią się od innych odpowiedzi w sieci Web. Dzięki tej elastyczności za pomocą skryptu CGI możliwe jest wygenerowanie wszystkiego, co serwer Web mógłby pobrać bezpośrednio z plików, włącznie z dokumentami HTML, zwykłymi dokumentami tekstowymi, plikami PDF, a nawet grafiką w formatach PNG lub GIF. Sposobami tworzenia dynamicznej grafiki zajmiemy się w rozdziale 13, „Tworzenie grafiki w sposób dynamiczny".
Przykładowa aplikacja CGl
Przyjrzyjmy się przykładowej aplikacji CGI napisanej w Perlu, tworzącej dynamiczne dane wyjściowe przedstawione przed chwilą w przykładzie 1.2. Program ten (przykład l .3) ustala, skąd się użytkownik łączy, a następnie tworzy prosty dokument HTML zawierający tę informację oraz wskazanie bieżącego czasu. W następnych kilku rozdziałach zobaczymy, jak posługując się różnymi modułami CGI jeszcze bardziej ułatwić sobie tworzenie takich aplikaq'i. Tymczasem podejdźmy do zagadnienia w sposób jak najprostszy.
Przykład 1.3. welcome.cgi#!/usr/bin/perl -wT
use strict;
my $czas = localtime;
my $zdalny_id = $ENV{REMOTE_HOST} || $ENV{REMOTE__ADDR};
my $email_admina = $ENV{SERVER_ADMIN};
print "Content-type: text/html\n\n";
print <<KONIEC_STRONY;
<HTML>
<HEAD>
<TITLE>Zapraszamy do bazy danych Mechaników Mikę'a</TITLE>
</HEAD>
<BODY BGCOLOR="#ffffff">
<IMG SRC="/images/mike.jpg" ALT="Mechanicy Mike’a“>
<P>Witamy w serwisie Szdalny_id! Co tu można znaleźć? Listę mechaników z całego kraju oraz rodzaj oferowanych przez nich usług — stworzoną na podstawie uwag i propozycji użytkowników.</P>
<P>Na co czekasz? Kliknij <A HREF="/cgi/lista.cgi">tutaj</A>, aby przejrzeć listę.</P>
<HR>
<P>Bieżące wskazanie czasu według serwera: $czas.</P>
<P>Jeśli natrafisz na jakieś problemy w naszym serwisie lub zechcesz zgłosić nam swoje propozycje, napisz do nas na adres elektroniczny <A HREF="mailto:$email_admina">Semail_admina</A>.</P>
</BODY>
</HTML>
KONIEC_STRONY
Powyższy program jest bardzo prosty. Zawiera tylko sześć poleceń, chociaż ostatnie składa się z wielu wierszy. Przeanalizujmy jego działanie. Ponieważ jest to nasz pierwszy skrypt, a przy tym krótki, przyjrzymy się mu linijka po linijce, choć, o czym wspomnieliśmy w „Przedmowie", zakładamy, że czytelnik jest z Perlem obeznany. Jeżeli więc wiedza o Perlu nie jest zbyt duża lub wymaga odkurzenia, przydać się może jakieś kompendium dotyczące tego języka, które na wszelki wypadek byłoby pod ręką podczas czytania tej książki. Polecamy Perl - programowanie - wydanie drugie Larry'ego Walia, Toma Christiansena i Jona Orwanta (Wydawnictwo RM). Księga ta dotyczy nie tylko standardowego Perla, lecz zawiera również opis wbudowanych funkcji tego języka w wygodnym układzie alfabetycznym.
Pierwszy wiersz programu wygląda tak, jak początek większości skryptów w Perlu. Informuje serwer, aby do interpretacji i wykonania skryptu użył programu znajdującego się w katalogu /usr/bin/perl. Odcyfrowywanie znaczników może sprawiać problemy: znaczniki -wT nakazują Perłowi włączyć ostrzeżenia oraz sprawdzanie w trybie kontroli skażeń. Ostrzeżenia pomagają przy ustalaniu miejsca trudno dostrzegalnych problemów nie mających charakteru błędów składniowych; włączenie ich nie jest konieczne, niemniej są one bardzo pożyteczne. Sprawdzanie w trybie kontroli skażeń nie powinno być traktowane jako fakultatywne: funkcję tę należy włączać we wszystkich skryptach CGI, chyba że ktoś lubi ryzyko. Ten rodzaj sprawdzania omawiamy w rozdziale 8, „Bezpieczeństwo".
Polecenie use strict nakazuje Perłowi włączenie ścisłych reguł w odniesieniu do zmiennych, procedur i referencji. Gdy ktoś dotąd nie stosował tego polecenia, powinien wypracować w sobie nawyk umieszczania go we wszystkich skryptach CGI. Tak jak ostrzeżenia, pomaga w znalezieniu drobnych pomyłek, na przykład literówek, które w innym wypadku mogłyby nie zostać zasygnalizowane jako błąd składniowy. Co więcej, pragma strict wykształca dobry zwyczaj programistyczny, wymuszając deklarowanie zmiennych i redukowanie liczby zmiennych globalnych. Dzięki temu łatwiej jest zapanować nad powstałym kodem. Na koniec, co zobaczymy w rozdziale 17, „Efektywność i optymalizacja", pragma strict jest bezwzględnie wymagana przez FastCGI oraz mod_perl. Przewidując migrację do któregoś z tych rozwiązań, od samego początku należy używać pragmy strict.
Teraz przejdziemy do rzeczy naprawdę istotnych. Najpierw ustanawiamy trzy zmienne. Pierwszej z nich, $czas, przypisujemy łańcuch reprezentujący bieżące datę i godzinę. Drugiej, $zdalny_id, przypisujemy identyfikator zdalnej maszyny zgłaszającej żądanie tej właśnie strony. Odpowiednie informacje uzyskujemy ze zmiennych środowiska REMOTE_HOST lub REMOTE_ADDR. Jak już wcześniej wspomnieliśmy, skrypty CGI wszystkie informacje z serwera Web uzyskują ze zmiennych środowiska oraz STDIN. REMOTE _HOST zawiera pełną nazwę domeny maszyny zdalnej, ale tylko wtedy, gdy zwrotne wyszukanie nazwy domeny zostało udostępnione serwerowi Web - w przeciwnym razie zmienna jest pusta. W takiej sytuacji korzystamy ze zmiennej REMOTE_ADDR, zawierającej adres IP maszyny zdalnej. Ostatniej zmiennej, $email_admina, przypisujemy zmienną SERVER_ADMIN, która zawiera adres poczty elektronicznej administratora serwera zgodny z podanym w plikach konfiguracyjnych serwera. Skrypty CGI mają dostęp do niewielu zmiennych środowiskowych. Wymienionym trzem i pozostałym przyjrzymy się bliżej w rozdziale 3, „CGI - wspólny interfejs bramy".
Wiemy już, że jeśli skrypt CGI ma zwrócić nowy dokument, najpierw musi przekazać na wyjście nagłówek HTTP deklarujący typ zwracanego dokumentu. Robi to, po czym drukuje dodatkowy pusty wiersz, który sygnalizuje, że zakończone zostało wysyłanie nagłówków. Następnie drukuje zasadniczą część dokumentu.
Zamiast używać instrukcji print osobno do każdego wiersza wysyłanego na wyjście standardowe, korzystamy z dokumentu „tutejszego", dzięki czemu możliwe jest wydrukowanie naraz całego bloku tekstu. Jest to standardowa właściwość Perla, która wydaje się być nieco ezoteryczna; mogą jej nie znać osoby, które nie zajmowały się dotąd jakimkolwiek oprogramowywaniem powłok. Polecenie to nakazuje Perłowi wydrukowanie wszystkich następnych wierszy, aż do napotkania w osobnym wierszu etykiety końca bloku (w tym wypadku jest to KONIEC_STRONY). Wiersze te traktuje jak tekst ujęty w znaki podwójnego cudzysłowu, a więc zmienne są wyliczane, przy czym podwójne cudzysłowy nie muszą być maskowane przed interpretacją. Dokumenty „tutejsze" nie tylko oszczędzają nam dodatkowego pisania, lecz również poprawiają czytelność programu. Jest jednak jeszcze lepszy sposób na generowanie HTML-a, co pokażemy w rozdziale 5, „CGI.pm", oraz w rozdziale 6, „Szablony HTML".
To już cały skrypt, więc w tym momencie kończy się jego działanie; serwer Web dodaje dodatkowe nagłówki HTTP i zwraca do klienta odpowiedź przedstawioną w przykładzie 1.2. Był to zaledwie prosty przykład skryptu CGI, więc niech nas nie zaprzątają pytania lub wątpliwości co do niektórych szczegółów. Właśnie im poświęcamy resztę książki, o czym świadczą liczne odniesienia do dalszych rozdziałów.
Wywoływanie skryptów CGISkrypty CGI mają własne URL-e, tak jak dokumenty HTML i inne zasoby w sieci Web. Serwer jest zwykle skonfigurowany tak, że określony katalog wirtualny (katalog zawarty w URL-u) wskazuje katalog skryptów CGI, na przykład /cgi-bin, /cgi, /scripts itp. Zarówno położenie skryptów CGI w systemie plików serwera, jak i odpowia...
[ Pobierz całość w formacie PDF ]