File Coverage

blib/lib/AnyEvent/HTTPD/Router.pm
Criterion Covered Total %
statement 62 65 95.3
branch 20 24 83.3
condition 4 7 57.1
subroutine 10 11 90.9
pod 3 3 100.0
total 99 110 90.0


line stmt bran cond sub pod time code
1             package AnyEvent::HTTPD::Router;
2              
3 7     7   516814 use common::sense;
  7         81  
  7         53  
4 7     7   3559 use parent 'AnyEvent::HTTPD';
  7         2123  
  7         38  
5              
6 7     7   574778 use AnyEvent::HTTPD;
  7         20  
  7         172  
7 7     7   43 use Carp;
  7         16  
  7         427  
8              
9 7     7   3497 use AnyEvent::HTTPD::Router::DefaultDispatcher;
  7         23  
  7         5726  
10             our $VERSION = '1.0.1';
11              
12             sub new {
13 5     5 1 1714 my $this = shift;
14 5   33     33 my $class = ref($this) || $this;
15 5         18 my %args = @_;
16              
17             # todo documentation how to overwrite your dispathing
18 5         15 my $dispatcher = delete $args{dispatcher};
19 5         13 my $routes = delete $args{routes};
20 5         10 my $auto_respond_404 = delete $args{auto_respond_404};
21             my $dispatcher_class = delete $args{dispatcher_class}
22 5   50     25 || 'AnyEvent::HTTPD::Router::DefaultDispatcher';
23             my $known_methods = delete $args{known_methods}
24 5   100     31 || [ qw/GET HEAD POST PUT PATCH DELETE TRACE OPTIONS CONNECT/ ];
25              
26 5         53 my $self = $class->SUPER::new(%args);
27              
28 5         15072 $self->{known_methods} = $known_methods;
29 5 50       60 $self->{dispatcher} = defined $dispatcher
30             ? $dispatcher
31             : $dispatcher_class->new();
32              
33             $self->reg_cb(
34             'request' => sub {
35 2     2   9962 my $self = shift;
36 2         5 my $req = shift;
37 2         12 my $matched = $self->dispatcher->match( $self, $req );
38 2 100       9 unless ($matched) {
39 1         8 $self->event( 'no_route_found' => $req );
40             }
41             },
42 5         41 );
43              
44             $self->reg_cb('no_route_found' => sub {
45 0     0   0 my ( $httpd, $req ) = @_;
46 0         0 $req->respond( [ 404, 'not found', {}, '' ] );
47 5 50       410 }) if $auto_respond_404;
48              
49 5 50       17 if ($routes) {
50 0         0 $self->reg_routes( @$routes );
51             }
52              
53 5         70 return $self;
54             }
55              
56 6     6 1 36 sub dispatcher { shift->{dispatcher} }
57              
58             sub _check_verb {
59 7     7   13 my $self = shift;
60 7         13 my $verb = shift;
61 7         11 my $methods = shift;
62              
63 7 100       22 if ( $verb =~ m/^:/ ) {
    100          
64 1         5 $methods->{$_}++ for qw(GET POST); # convert ':verbs' to POST and GET
65 1         4 return 1;
66 39         80 } elsif ( grep { $verb eq $_ } @{ $self->{known_methods} } ) {
  6         17  
67 3         57 $methods->{$verb}++;
68 3         16 return 1;
69             }
70              
71 3         38 return;
72             }
73              
74             sub reg_routes {
75 12     12 1 6890 my $self = shift;
76              
77 12 100       50 croak 'arguments to reg_routes are required' if @_ == 0;
78 11 100       53 croak 'arguments to reg_routes are confusing' if @_ % 3 != 0;
79              
80             # * mix allowed methods and new http methods together
81 10         15 my %methods = map { $_ => 1 } @{ $self->allowed_methods };
  26         98  
  10         44  
82              
83 10         52 while (my ($verbs, $path, $cb) = splice(@_, 0, 3) ) {
84              
85 10 50       37 $verbs = ref($verbs) eq 'ARRAY'
86             ? $verbs
87             : [ $verbs ];
88              
89 10 100       59 if ( not ref($cb) eq 'CODE' ) {
    100          
90 1         12 croak 'callback must be a coderef';
91             }
92             elsif ( not $path =~ m/^\// ) {
93 2         21 croak 'path syntax is wrong';
94             }
95 7         18 foreach my $verb (@$verbs) {
96 7 100       21 croak 'verbs or methods are wrong'
97             unless $self->_check_verb( $verb, \%methods );
98             }
99              
100 4         16 $self->dispatcher->add_route($verbs, $path, $cb);
101             }
102              
103             # set allowed methods new
104             # Todo: setter doesnt work in this AE::HTTPD version
105             # so must do push(@{$self->{allowed_methods}}
106             # later we can do setter if AE::HTTPD version is high enough
107 4         34 $self->{allowed_methods} = [ sort keys %methods ];
108             }
109              
110             1;
111              
112             __END__