Az előző posztban már emlegettem hogy remek dolog az nginx embedded perl modulja, leírtam az nginx installt és a perl modul konfigurálása is megvolt. Most akkor lássuk, hogyan is ír az ember remek url handlereket perlben nginx-hez.
Perl packaget (vagy packageket) kell írnunk, a konfigban pedig a megfelelő helyen meghívni a package megfelelő függvényét. Ahhoz hogy működjön a dolog, szükségünk van az nginx csomagra (use nginx; az elején). Az nginx által meghívott függvény paraméterben kap egy request objektumot, minden lényeges dolog ebben van. A legfontosabb mezői:
$r->uri : request uri, GET paraméterek nélkül (pl /testapp/helloworld )
$r->args : GET paraméter string (pl debug=1 )
$r->header_only : true ha csak headert kell visszaadni
$r->remote_addr : távoli IP
Legfontosabb metódusai:
$r->print() : output kiírása
A http válaszkódot a függvény visszatérési értéke határozza meg. Remek konstansok állnak rendelkezésünkre ehhez, mint pl OK (ami azonos a HTTP_OK -val), HTTP_NOT_FOUND, HTTP_BAD_REQUEST stb.
$r->send_http_header() : http header kiadása, Content Type paraméterben adható meg
$r->header_out() : bármilyen header kiadása, név és érték a két paramétere
$r->rflush() : output azonnali elküldése
Ezek segítségével már nem okozhat gondot egy egyszerű url handler megírása. Minden a hello world alkalmazással kezdődik, hát íme:
package helloworld;
Ezt az előző posztban szereplő location konfiggal már be is lehet kapcsolni (ne felejtsük el a perl_require-t a server blokkba valahova betenni: perl_require /path/to/file/helloworld.pm).
use nginx;
sub url_handler {
my $r = shift;
$r->print("Hello World");
$r->rflush();
return OK;
}
1;
__END__
Egy kicsit összetettebb példát is adok, erre az url patternre: /file/$folder/$number?div=$div. Itt a $number $div-vel adott maradékából képezünk egy filenevet, ha ez a file létezik a folderben akkor kiszolgáljuk, ha nem 404-et adunk. Ha nem kapunk $div paramétert, megadott defaulttal osztunk. Ha nem kapunk foldert vagy numbert, bad request a válasz.
package filepelda;
use nginx;
my $rootdir = "/var/www/data/";
my $defaultdiv = 5;
# url minta: /file/$folder/$number?div=$div
sub url_handler {
my $r = shift;
my @urlParts = split('\/', $r->uri, 4);
if (@urlParts != 4) {
return HTTP_BAD_REQUEST;
}
shift @urlParts; # az elso resz ures
shift @urlParts; # "file"
my $folder = shift @urlParts;
my $number = shift @urlParts;
my $args = $r->args;
my ($div) = $args =~ /div=(\d+)/;
if (!$div) {
$div = $defaultdiv;
}
my $target = $number % $div;
my $filename = $rootdir . $folder . "/" . $target;
if (-e $filename) {
$r->send_http_header("application/octet-stream");
open(DATA, $filename);
while(<DATA>)
{
$r->print("$_");
}
$r->rflush();
return OK;
} else {
return HTTP_NOT_FOUND;
}
}
1;
__END__
További részletek a request objektumról és a perl modulról itt. Jó szórakozást kívánok hozzá!