File Coverage

blib/lib/Router/Simple/Route.pm
Criterion Covered Total %
statement 75 75 100.0
branch 41 44 93.1
condition 9 10 90.0
subroutine 6 6 100.0
pod 0 2 0.0
total 131 137 95.6


line stmt bran cond sub pod time code
1             package Router::Simple::Route;
2 11     11   124 use strict;
  11         22  
  11         429  
3 11     11   55 use warnings;
  11         372  
  11         284  
4 11     11   56 use Carp ();
  11         18  
  11         423  
5              
6             use Class::Accessor::Lite 0.05 (
7 11         105 rw => [qw(name dest on_match method host pattern)],
8 11     11   13892 );
  11         18025  
9              
10             sub new {
11 36     36 0 54 my $class = shift;
12              
13             # connect([$name, ]$pattern[, \%dest[, \%opt]])
14 36 100 100     222 if (@_ == 1 || ref $_[1]) {
15 31         61 unshift(@_, undef);
16             }
17              
18 36         70 my ($name, $pattern, $dest, $opt) = @_;
19 36 50       102 Carp::croak("missing pattern") unless $pattern;
20 36         135 my $row = +{
21             name => $name,
22             dest => $dest,
23             on_match => $opt->{on_match},
24             };
25 36 100       209 if (my $method = $opt->{method}) {
26 19 50       121 $method = [$method] unless ref $method;
27 19         38 $row->{method} = $method;
28              
29 19         25 my $method_re = join '|', @{$method};
  19         43  
30 19         205 $row->{method_re} = qr{^(?:$method_re)$};
31             }
32 36 100       111 if (my $host = $opt->{host}) {
33 5         9 $row->{host} = $host;
34 5 50       64 $row->{host_re} = ref $host ? $host : qr(^\Q$host\E$);
35             }
36              
37 36         77 $row->{pattern} = $pattern;
38              
39             # compile pattern
40 36         41 my @capture;
41 36         41 $row->{pattern_re} = do {
42 36 100       80 if (ref $pattern) {
43 2         4 $row->{_regexp_capture} = 1;
44 2         5 $pattern;
45             } else {
46 34         187 $pattern =~ s!
47             \{((?:\{[0-9,]+\}|[^{}]+)+)\} | # /blog/{year:\d{4}}
48             :([A-Za-z0-9_]+) | # /blog/:year
49             (\*) | # /blog/*/*
50             ([^{:*]+) # normal string
51             !
52 84 100       310 if ($1) {
    100          
    100          
53 23         85 my ($name, $pattern) = split /:/, $1, 2;
54 23         41 push @capture, $name;
55 23 100       102 $pattern ? "($pattern)" : "([^/]+)";
56             } elsif ($2) {
57 5         13 push @capture, $2;
58 5         16 "([^/]+)";
59             } elsif ($3) {
60 4         7 push @capture, '__splat__';
61 4         20 "(.+)";
62             } else {
63 52         226 quotemeta($4);
64             }
65             !gex;
66 34         630 qr{^$pattern$};
67             }
68             };
69 36         91 $row->{capture} = \@capture;
70 36   100     110 $row->{dest} ||= +{};
71              
72 36         183 return bless $row, $class;
73             }
74              
75             sub match {
76 91     91 0 124 my ($self, $env) = @_;
77              
78 91 100       267 if ($self->{host_re}) {
79 15 100       94 unless ($env->{HTTP_HOST} =~ $self->{host_re}) {
80 4         11 return undef;
81             }
82             }
83 87 100       534 if (my @captured = ($env->{PATH_INFO} =~ $self->{pattern_re})) {
84 33         1019 my %args;
85             my @splat;
86 33 100       1429 if ($self->{_regexp_capture}) {
87 1         4 push @splat, @captured;
88             } else {
89 32 100 100     38 if (@{$self->{capture}} > 0 && scalar(@{$self->{capture}}) != scalar(@captured)) {
  32         687  
  15         557  
90             # Should not contain parenthesis in regexp pattern
91             #
92             # Good: "/{date:(?:\d+)}"
93             # Bad: "/{date:(\d+)}"
94 1         164 Carp::carp("Path pattern should not contain paren. This code may not works in future version of Router::Simple. : " . $self->{pattern});
95             }
96              
97 32         131 for my $i (0..@{$self->{capture}}-1) {
  32         113  
98 29 100       522 if ($self->{capture}->[$i] eq '__splat__') {
99 4         10 push @splat, $captured[$i];
100             } else {
101 25         84 $args{$self->{capture}->[$i]} = $captured[$i];
102             }
103             }
104             }
105 33 100       132 if ($self->{method_re}) {
106 20 100 50     129 unless (($env->{REQUEST_METHOD} || '') =~ $self->{method_re}) {
107 6         9 $Router::Simple::_METHOD_NOT_ALLOWED = 1;
108 6         25 return undef;
109             }
110             }
111 27         172 my $match = +{
112 27 100       41 %{$self->{dest}},
113             %args,
114             ( @splat ? ( splat => \@splat ) : () ),
115             };
116 27 100       585 if ($self->{on_match}) {
117 3         13 my $ret = $self->{on_match}->($env, $match);
118 3 100       29 return undef unless $ret;
119             }
120 26         115 return $match;
121             }
122 54         139 return undef;
123             }
124              
125             1;
126             __END__