File Coverage

blib/lib/Plack/Builder/Conditionals.pm
Criterion Covered Total %
statement 96 101 95.0
branch 30 30 100.0
condition 16 21 76.1
subroutine 22 24 91.6
pod 8 8 100.0
total 172 184 93.4


line stmt bran cond sub pod time code
1             package Plack::Builder::Conditionals;
2              
3 4     4   186107 use strict;
  4         14  
  4         193  
4 4     4   27 use warnings;
  4         11  
  4         137  
5 4     4   8877 use Net::CIDR::Lite;
  4         19200  
  4         138  
6 4     4   6807 use List::MoreUtils qw//;
  4         8721  
  4         89  
7 4     4   2804 use Plack::Util;
  4         58062  
  4         117  
8 4     4   3134 use Plack::Middleware::Conditional;
  4         13481  
  4         331  
9              
10             our $VERSION = '0.05';
11              
12             sub import {
13 4     4   45 my $class = shift;
14 4         10 my $caller = caller;
15 4         14 my %args = @_;
16              
17 4         29 my @EXPORT = qw/match_if addr path method header browser any all/;
18              
19 4     4   28 no strict 'refs';
  4         6  
  4         4768  
20 4         38 my $i=0;
21 4         12 for my $sub (@EXPORT) {
22 32 100       82 my $sub_name = $args{'-prefix'} ? $args{'-prefix'} . '_' . $sub : $sub;
23 32         56 *{"$caller\::$sub_name"} = \&$sub;
  32         4999  
24             }
25             }
26              
27             sub match_if {
28 3     3 1 5 my $condition = shift;
29 3         7 my ( $mw, @args ) = @_;
30            
31 3 100       9 if (ref $mw ne 'CODE') {
32 1         8 my $mw_class = Plack::Util::load_class($mw, 'Plack::Middleware');
33 1     1   2002 $mw = sub { $mw_class->wrap($_[0], @args) };
  1         37  
34             }
35              
36             return sub {
37 3     3   240 Plack::Middleware::Conditional->wrap(
38             $_[0],
39             condition => $condition,
40             builder => $mw
41             );
42             }
43 3         16 }
44              
45             sub addr {
46 6     6 1 14 my $not;
47             my $ip;
48 6 100       11 if ( @_ == 1 ) {
49 5         7 $ip = $_[0];
50             }
51             else {
52 1         4 $not = $_[0];
53 1         2 $ip = $_[1];
54             }
55              
56 6 100       17 my @ip = ref $ip ? @$ip : ($ip);
57 6         19 my $cidr4 = Net::CIDR::Lite->new();
58 6         53 my $cidr6 = Net::CIDR::Lite->new();
59 6         38 for my $ip ( @ip ) {
60 9 100       259 if ( $ip =~ m!:! ) {
61 3         7 $cidr6->add_any($ip);
62             }
63             else {
64 6         16 $cidr4->add_any($ip);
65             }
66             }
67              
68             return sub {
69 6     6   7 my $env = shift;
70 6         8 my $find_ip;
71 6 100       15 if ( $env->{REMOTE_ADDR} =~ m!:! ) {
72 2         5 $find_ip = $cidr6->find($env->{REMOTE_ADDR});
73             }
74             else {
75 4         12 $find_ip = $cidr4->find($env->{REMOTE_ADDR});
76             }
77 6 100 66     362 return (defined $not && $not eq '!') ? !$find_ip : $find_ip;
78 6         797 };
79             }
80              
81             sub _match {
82 23     23   32 my $key = shift;
83 23         40 my $not;
84             my $val;
85 23 100       44 if ( @_ == 1 ) {
86 14         20 $val = $_[0];
87             }
88             else {
89 9         11 $not = $_[0];
90 9         12 $val = $_[1];
91             }
92              
93             return sub {
94 29     29   67549 my $env = shift;
95 29         29 my $ret;
96 29 100 66     112 if ( ref $val && ref $val eq 'Regexp' ) {
    100          
97 9   66     68 $ret = exists $env->{$key} && $env->{$key} =~ m!$val!;
98             }
99             elsif ( defined $val ) {
100 18   100     92 $ret = exists $env->{$key} && $env->{$key} eq $val;
101             }
102             else {
103 2         3 $ret = exists $env->{$key};
104             }
105 29 100 66     161 return ( defined $not && $not eq '!' ) ? !$ret : $ret;
106 23         121 };
107             }
108              
109             sub path {
110 8     8 1 92 _match( 'PATH_INFO', @_ );
111             }
112              
113             sub method {
114 9     9 1 15 my $not;
115             my $method;
116 9 100 100     50 if ( defined $_[0] && $_[0] eq '!' ) {
117 4         8 $not = shift;
118             }
119 9 100   1   24 return sub { 1 } unless @_;
  1         3  
120 8 100       19 if ( @_ == 1 ) {
121 6         10 $method = $_[0];
122             }
123             else {
124 2         4 my $alternatives = join '|', map { quotemeta($_) } @_;
  4         11  
125 2         75 $method = qr/^(?:$alternatives)$/i;
126             }
127 8 100 66     39 if ( defined $method && ! ref $method ) {
128 4         8 $method = uc $method;
129             }
130 8         15 _match( 'REQUEST_METHOD', grep { defined } $not, $method );
  16         28  
131             }
132              
133             sub header {
134 5     5 1 8 my $header = shift;
135 5         13 $header =~ s/-/_/g;
136 5         8 $header = 'HTTP_' . uc($header);
137 5         11 _match( $header, @_ );
138             }
139              
140             sub browser {
141 2     2 1 4 _match( "HTTP_USER_AGENT", @_ );
142             }
143              
144             sub any {
145 0     0 1 0 my @match = @_;
146             return sub {
147 0     0   0 my $env = shift;
148 0         0 List::MoreUtils::any { $_->($env) } @match;
  0         0  
149 0         0 };
150             }
151              
152             sub all {
153 1     1 1 3 my @match = @_;
154             return sub {
155 4     4   167 my $env = shift;
156 4         35 List::MoreUtils::all { $_->($env) } @match;
  5         11  
157 1         7 };
158             }
159              
160              
161             1;
162             __END__