HTTP:Daemon in Perl

Yesterday I tried socket in Perl in post Socket in Perl. Today I will share my experience in HTTP:Daemon.

Basically HTTP package implements the necessary elements defined in http://tools.ietf.org/pdf/rfc2616.pdf (Hypertext Transfer Protocol — HTTP/1.1). For example, on my post Socket in Perl yesterday, the connection is established using socket and it doesn’t support cache and this brings unnecessary network load.  However from http://tools.ietf.org/pdf/rfc2616.pdf, it defines the GET method as below. (I tested HTTP:Daemon seems it is implemented well to support cache).

9.3 GET
The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI.
If the Request-URI refers to a data-producing process, it is the produced data which shall be returned as the entity
in the response and not the source text of the process, unless that text happens to be the output of the process.
The semantics of the GET method change to a “conditional GET” if the request message includes an IfModified-Since, If-Unmodified-Since, If-Match, If-None-Match, or If-Range header field. A
conditional GET method requests that the entity be transferred only under the circumstances described by the
conditional header field(s). The conditional GET method is intended to reduce unnecessary network usage by
allowing cached entities to be refreshed without requiring multiple requests or transferring data already held by the
client

API provided by HTTP:Daemon from http://search.cpan.org/~gaas/libwww-perl-5.837/lib/HTTP/Daemon.pm

Additionally, I introduced the fork in this Daemon script.

The logic in the script:

1. Accept a http request connection.

2. Fork a process to take care of the request.

3. Return to 1.

camelhttp.pm:

package camelhttp;

use strict;
use HTTP::Daemon;
use HTTP::Status;
use Carp;
use FileHandle;
use camellogger;
use camelutils;

my $portno = "8080";
my $base_dir = "../webapps";
my $SERVER = HTTP::Daemon->new(LocalPort => $portno, LocalAddr => 'localhost')
 or die;
loader();
camelHttpCore();

END{
_destroy();
}

sub camelHttpCore{

# autoreaping of zombies
$SIG{CHLD} = 'IGNORE';
while (1)
{
while (my $con = $SERVER->accept){
logger(0, "$0 - Camel is forking a worker");
next if my $pid = fork; #parent
die logger(0, "$0 - Camel can't fork a worker : $!") unless defined $pid;
while (my $req = $con->get_request){

my $path = $base_dir . $req->uri->path;
if ($req->method eq 'GET'){
if (_handleGet($path) eq "YES"){
$con->send_file_response("$path");
} else {
$con->send_error(RC_NOT_FOUND);
}

} elsif ($req->method eq 'POST') {
$con->send_error(RC_FORBIDDEN);
}
}
close($con);
exit;
} continue {
# nothing here so far.
}
}
}

sub _handleGet{
my ($path) = @_;
if ($fshash{"$path"}){
return "YES";
} else {
return "NO";
}
}

sub _destroy {
logger(0, "$0 - Camel is destroying itself");
close ($SERVER) if (defined $SERVER);
}

 1;