File Coverage

blib/lib/HTTP/AppServer/Base.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             package HTTP::AppServer::Base;
2             # Simple HTTP server that uses regular expressions
3             # to disptach URLs to Perl function references that contain the logic.
4             # 2010 by Tom Kirchner
5              
6 1     1   33 use 5.010000;
  1         5  
  1         47  
7 1     1   7 use strict;
  1         2  
  1         41  
8 1     1   6 use warnings;
  1         1  
  1         40  
9 1     1   5 use Data::Dumper;
  1         2  
  1         47  
10 1     1   562 use HTTP::Server::Simple::CGI;
  0            
  0            
11             use base qw(HTTP::Server::Simple::CGI);
12              
13             our $VERSION = '0.01';
14              
15             # defines a handler (function reference) for each dispatching handler
16             my $Handlers = [
17             # {'regex' => , 'handler' => or }
18             ];
19              
20             sub set
21             {
22             my ($self, $name, $value) = @_;
23             if (exists $self->{'sets'}->{$name}) {
24             die "Cannot set key '$name' more than once.\n";
25             } else {
26             $self->{'sets'}->{$name} = $value;
27            
28             # store name of plugin
29             my $caller = caller();
30             $caller =~ s/.*\://g;
31             $self->{'sets-plugins'}->{$name} = $caller;
32             }
33             return $self;
34             }
35              
36             sub AUTOLOAD
37             {
38             my ($self, @args) = @_;
39              
40             my $name = $HTTP::AppServer::Base::AUTOLOAD;
41             $name =~ s/.*\://g;
42            
43             if (exists $self->{'sets'}->{$name}) {
44             my $value = $self->{'sets'}->{$name};
45             if (ref $value eq 'CODE') {
46             # call method
47             return $value->($self, @args);
48             }
49             else {
50             if (scalar @args > 0) {
51             # set property
52             $self->{'sets'}->{$name} = $args[0];
53             }
54             # get property
55             return $self->{'sets'}->{$name};
56             }
57             }
58             else {
59             eval('return SUPER::'.$name.'(@args)');
60             }
61             #else {
62             # print STDERR "Access to unknown property or method '$name'\n";
63             # return ();
64             #}
65             }
66              
67             sub debug
68             {
69             my ($self) = @_;
70             print "\nroutes:\n";
71             map { print " ".$_->{'regex'}."\n" } @{$Handlers};
72             print "\nproperties and methods:\n";
73             map { print " ".sprintf('%-16s',$_)." (plugin ".$self->{'sets-plugins'}->{$_}.")\n" } sort keys %{$self->{'sets'}};
74             print "\n";
75             }
76              
77             sub handle
78             {
79             my ($self, $regex, $handler) = @_;
80             push @{$Handlers}, {'regex' => $regex, 'handler' => $handler};
81             return $self;
82             }
83              
84             sub handle_request
85             {
86             my ($self, $cgi) = @_;
87             unless ($self->_dispatch_path($cgi, $cgi->path_info(), {})) {
88             # return an error
89             $self->errorpage();
90             return 0;
91             }
92             return 1;
93             }
94              
95             sub _dispatch_path
96             {
97             my ($self, $cgi, $path, $called) = @_;
98              
99             # try to find dispatch for current request
100             my $i = 0;
101             foreach my $h (@{$Handlers}) {
102             my $regex = $h->{'regex'};
103             my $handler = $h->{'handler'};
104             #print STDERR
105             # "[$i] $regex ($path) ".
106             # "(called? ".(exists $called->{"$i"} == 1 ? '1':'0').") ".
107             # "(match? ".($path =~ /$regex/ == 1 ? '1':'0').")\n";
108             if (!exists $called->{"$i"} && $path =~ /$regex/) {
109             my (@parts) = $path =~ /$regex/;
110             if (ref $handler eq 'CODE') {
111             # handler is a function
112             my $result = $handler->( $self, $cgi, @parts );
113             $result = 1 unless defined $result;
114             #print STDERR " => $result\n";
115             $called->{"$i"} = 1;
116             if ($result == 0) {
117             # go on searching
118             #print STDERR " => go on\n";
119             return $self->_dispatch_path($cgi, $path, $called);
120             } else {
121             # stop here
122             #print STDERR " => stop\n";
123             return 1;
124             }
125             }
126             else {
127             # handler forwards to other handler
128             return $self->_dispatch_path($cgi, $handler, $called);
129             }
130             }
131             $i++;
132             }
133             return 0;
134             }
135              
136             1;