HTTP, CGI, Perl HTTP HyperText Transfer Protocol CGI Common Gateway Interface Perl Practical Extraction and Report Language Przeglądarka HTTP Serwer WWW CGI Moduł
HTTP (1) Protokół bezpołączeniowy działający na zasadzie połączenie (zwykle przez TCP/IP na porcie 80) żądanie klienta (użycie URI) odpowiedź serwera rozłączenie (serwer zamyka połączenie)
HTTP (2) Obecnie używane wersje: 1.0 i 1.1 W celu przyspieszenia komunikacji wprowadzono możliwość podtrzymywania połączenia w HTTP/1.0 (domyślnie włączone w HTTP/1.1) HTTPS rozszerzenie HTTP o szyfrowanie i uwierzytelnianie
Metody HTTP GET HEAD PUT POST DELETE OPTIONS TRACE CONNECT
URI (Uniform Resource Identifier) <protokół> :// <serwer> : <port> / <ścieżka>? <zapytanie> # <fragment> <protokół> :// użytkownik:hasło @ <serwer> : <port> / <ścieżka>? <zapytanie> # <fragment> Kodowanie znaków (url-encoded) & łączy wiele parametrów w zapytaniu, + spacja, % poprzedza zakodowany szesnastkowo znak.
Format przesyłanych danych Strumień danych tekstowych. Linie są zakończone znakami \r\n. Między nagłówkiem a danymi występuje jedna pusta linia. [Linia żądania/odpowiedzi] [Linie nagłówka dodatkowe parametry] [Dane opcjonalne]
Żądanie [Metoda URI Wersja HTTP] POST /cgi-bin/query HTTP/1.0 [Nagłówek ogólny] Connection: Keep-Alive [Nagłówek żądania] User-Agent: Mozilla.3.0 Gold (WinNT; I) Host: www.jakisserwer.com Accept: image/gif, image/x-bitmap, image/jpeg [Nagłowek zawartości] Content-type: application/x-www-form-urlencoded Content-length: 23 [Treść] query=knuth&type=autor
Odpowiedź [Wersja HTTP Kod st. Wynik op.] [Nagłówek ogólny] [Nagłówek odpowiedzi] [Nagłowek zawartości] HTTP/1.0 200 OK Date: Fri, 04, Oct 1996 14:31:51 GMT Server: Apache/1.1.1 Content-type: text/html Content-length: 33 Last-modified: Fri, 04, Oct 1996 14:06:11 GMT [Treść] <title>przykladowa strona</title>
Odpowiedź - odświeżanie Refresh: 60; http://www.mojserwer.com/cgi-bin/moje.cgi Expires: Tue, 09 Sep 1997 13:30:00 GMT Pragma: no-cache Las-modified: Tue, 09 Sep 1997 13:30:00 GMT
Odpowiedź - przekierowanie Location: http://www.mojserwer.com/index.html
Autoryzacja dostępu [WWW-Authenticate: schemat(basic,digest,ntlm) obszar autoryzacji] (login:hasło-base64) HTTP/1.0 401 Unauthorized WWW-Authenticate: BASIC realm="admin" GET /zamowienia.html HTTP/1.0 Authorization: BASIC d2xxxxxxxxx
Cookies ciasteczka HTTP/1.0 200 OK Set-Cookie: acct=04382374;domain=.mojserwer.com; Expires=Sun,16-Feb-2003 04:38:14 GMT;Path=/ GET /zamowienia.pl HTTP/1.0 Cookie: acct=04382374
Żądanie - GET Dane w metodzie GET są przesyłane w nagłówku razem ze ścieżką do zasobu. Za nagłówkiem nie występuje blok danych. Przykład: http://www.gdziestam.com/~user/script.pl?imie=lukasz&nazwisko=felsztukier http://www.gdziestam.com/~user/script.pl?nazwa=lukasz+felsztukier http://www.gdziestam.com/~user/script.pl?plik=%7eplik Wada: ograniczony rozmiar bufora wejściowego (różnie: 1KB lub 8KB)
Formularz HTML Atrybuty znacznika <FORM> ACTION="/cgi-bin/script.pl" METHOD="GET" lub "POST" ENCTYPE=application/x-www-form-urlencoded (def.) lub multipart/form-data
Żądanie - POST Dane w metodzie POST są przesyłane za nagłówkiem. W nagłówku żądania jest podany typ MIME (Multipart Internet Mail Extension) oraz rozmiar danych. Wysyłanie plików do serwera: <form method="post" action="post.pl" enctype="multipart/form-data"> Podaj nazwe pliku:<br> <input name="plik" type="file"><br> <input name="wyslij" type="submit"> </form>
CGI Interfejs komunikacyjny między serwerem WWW a modułem wykonawczym Bazuje na: zmiennych środowiskowych standardowym wejściu/wyjściu programu
CGI (2) Ustawiona zmienna środowiskowa: REQUEST_METHOD='POST' lub 'GET' Dane wejściowe należy wczytać ze: zmiennej środowiskowej QUERY_STRING (metoda GET) standardowego wejścia; rozmiar danych podany w CONTENT_LENGTH (metoda POST) Wynik (nagłówek HTTP i zawartość) należy wysłać na standardowe wyjście.
CGI (3) Informacje: REMOTE_ADDR, REMOTE_HOST, HTTP_USER_AGENT SERVER_NAME, SERVER_PORT, SERVER_PROTOCOL SCRIPT_NAME, HTTP_REFERER Autoryzacja: AUTH_TYPE='Basic', REMOTE_USER
Perl Skrypty w Unixie Zmienne Skalarne Tablice Tablice asocjacyjne Wyrażenia warunkowe Pętle Operacje na zmiennych Procedury i funkcje Operacje we/wy Wczytanie danych Wysyłanie danych do serwera WWW (standardowe wyjście) Obsługa plików Wyrażenia regularne Dekodowanie żądania Baza danych
Perl język skryptowy W systemie Unix każdy plik o dowolnym rozszerzeniu może być skryptem, musi tylko: posiadać atrybut 'wykonywalności' wskazywać na jego interpreter (za pomocą znaków #!, za którymi znajduje się ścieżka do interpretera), np.: #!/usr/local/bin/perl -w (w pozostałych przypadkach znak # rozpoczyna komentarz.)
Zmienne skalarne ($ nie trzeba definiować typu): $liczba = 4; $ulamek = 5.34; $duza_liczba = 2_345_432; $wykladnicza = 3e-4; $l_oct = 012; $l_hex = 0x3f; $lancuch = "Jakiś łańcuch"; # rozwijanie zmiennych $inny_lancuch = 'Inny łańcuch';
Zmienne skalarne (2) Większość operatorów taka sama jak w języku C. Różnice: ** (potęgowanie) <=> (porównanie; zwraca -1, 0, 1) eq, ne, gt, lt, ge, le (porównania łańcuchów tekstowych). (łączenie napisów, np.: "Ala"." ma") x (powielanie napisów, np.: "kot" x 3)
Tablice (@ uporządkowany zbiór danych skalarnych indeksowany od 0): @liczby = (1, 23, 5, 16, 0); @lancuchy = ('styczeń', 'luty', 'marzec', 'kwiecień'); @rozne = (3.25, 'wtorek', $zmienna, 3+5); @liczby = (1..100); @litery = ('a'..'r');
Tablice (2) $tablica[4] = 'piąty element'; Ostatni indeks: $#nazwa_tablicy Rozmiar tablicy: $liczba_elem = @nazwa_tabl; Sortowanie: @uporzadkowane = sort @nieuporzadkowane; @uporzadkowane = sort {$a <=> $b} @nieuporzadkowane; @ARGV parametry przekazane do skryptu (bez nazwy skryptu zawartej w $0).
Tablice asocjacyjne (% uporządkowany zbiór par danych skalarnych): %wiek = ('Ola', 15, 'Kasia', 13, 'Jaś', 10); %wiek = ('Ola'=>15, 'Kasia'=>13, 'Jaś'=>10); $wiek{'kasia'}; # zwróci wiek Kasi $wiek{'jola'} = 8; # doda wiek Joli # zwróci wiek Kasi i usunie Kasię z tablicy delete $wiek{'kasia'};
Wyrażenia warunkowe if (test1) { # blok1; } elsif (test2) { # blok2; } else { # blokn; } unless (test) { # przeciwieństwo if # blok1; } else { # blok2; } test? wyr_prawdy : wyr_fałszu;
Pętle while (test) { # blok poleceń; } until (test) { # blok poleceń; } do { # blok poleceń; } while (test); do { # blok poleceń; } until (test);
Pętle (2) for ($i = 1; $i < 6; $I ++) { print $i; } foreach $zmienna (@tablica) { # blok poleceń; } foreach $zmienna (keys %tablica_rozpr) { # bok poleceń; } foreach $zmienna (1..5) {... } Przerywanie wykonania pętli: last, next, redo.
Operacje na zmiennych Wycinek tablicy @tablica = ('poniedziałek', 'wtorek', 'środa', 'czwartek', 'piątek', 'sobota', 'niedziela'); @wycinek_tablicy = @tablica[0, 3, 4]; @wycinek_tablicy = @tablica[1..4]; $fragment = substr('poniedziałek', 2, 5);# zwróci "niedz" @lista = split(';', $lancuch); $lancuch = join(';', @lista); # podział tekstu # złączenie komórek @zwiekszone = map {$_++} @liczby; # wykonanie operacji na każdym elemencie
Procedury i funkcje sub nazwa { # instrukcje; } sub iloczyn { # instrukcje; $liczba1 * $liczba2; } sub iloczyn { # instrukcje; return $liczba1 * $liczba2; }
Procedury i funkcje (2) &nazwa_procedury(); # & jest opcjonalne wywołanie $il = &iloczyn(); sub suma { # argumanty przechowywane w tablicy @_ return $_[0] + $_[1] + $_[2]; } $s = &suma($argument1, $argument2, $argument3);
Wczytanie danych # jedna linia ze standardowego wejścia $skalar = <STDIN>; # każda linia w osobnej komórce @tablica = <STDIN>;
Wypisanie wyników print "Content-type: text/html\n\n"; print STDOUT "Hello, World!"; print sprintf("%.3f", 10/3);
Wypisanie wyników (2) print <<ogranicznik; <HTML> <HEAD> <TITLE>Informacje o poprzednim uzytkowniku</title> </HEAD> <BODY BGCOLOR="#FFFFFF"> ogranicznik
Obsługa plików open(plik, "plik.txt") die "Nie można otworzyć pliku"; while ($scalar = <PLIK>) { # operacje na zmiennej $scalar; } open(plik, ">plik.txt"); open(plik, ">>plik.txt"); print PLIK "Dane do pliku"; close PLIK; # otwarcie pliku do zapisu # otwarcie pliku do dopisywania
Wyrażenia regularne (1) Kod Klasa zn. Znaczenie \d [0-9] Dowolna cyfra \D [^0-9] Dowolny znak nie będący cyfrą \w [0-9a-zA-Z] Dowolny "znak słowa" \W [^0-9a-zA-Z]Dowolny znak nie będący "znakiem słowa" \s [ \t\n\r\f] Znaki białe (spacja, tabulator, nowy wiersz, powrót karetki, wysunięcie strony) \S [^ \t\n\r\f] Dowolny znak nie będący znakiem białym
Wyrażenia regularne (2) Dopasowanie ('match') zwraca 'boolean' $lancuch =~ m/wyrazenie/; # match $lancuch!~ m/wyrazenie/i; # not match # 'i' nie zwraca uwagi na duże i małe litery m/wyrazenie/; # match na zmiennej $_
Wyrażenia regularne (3) Zamiana napisów ('substitute') zmienia tekst # zamiana 'ala' na 'Ala' $zmienna =~ s/ala/ala/; $zmienna =~ s/ala/ala/g; # 'g' zamienia wszystkie wystąpienia # 'i' nie zwraca uwagi na duże i małe litery # 'e' wykonuje ewaluację kodu
Wyrażenia regularne (4) Zamiana znaków ('translate') zmienia tekst # zamiana na duże litery $zmienna =~ tr/a,b,c/a,b,c/; $zmienna =~ tr/[a-z]/[a-z]/;
Wyrażenia regularne (5) Odwołania wsteczne i zapamiętywanie wzorców: s/(\s+)\b/x$1x/g m/^(\s+)\sala \1/ if (m/^(\s+)\sala \1/) print $1;
Dekodowanie żądania (1a) if ( $ENV{'REQUEST_METHOD'} eq "GET" ) { $buffer = $ENV{'QUERY_STRING'}; } elsif ($ENV{'REQUEST_METHOD'} eq "POST") { read(stdin, $buffer, $ENV{'CONTENT_LENGTH'}); }
Dekodowanie żądania (1b) if ($ENV{'CONTENT_LENGTH'} > 0) { read(stdin, $buffer, $ENV{'CONTENT_LENGTH'}); $buffer.="&".$env{'query_string'} if length $ENV{'QUERY_STRING'}; } else { $buffer=$env{'query_string'}; }
Dekodowanie żądania (2) @pairs = split(/&/, $buffer); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%([0-9a-f]{2})/pack("c", hex($1))/egi; $FORM{$name} = $value; }
use DBI; Baza danych $dbh = DBI->connect( "DBI:mysql:baza:127.0.0.1", user, hasło ); $sql = "SELECT * FROM blah_table"; $sth = $dbh->prepare($sql); $sth->execute; while ($row = $sth->fetchrow_hashref) { } print $row->{'nazwa_wiersza'},'<br>';