File Coverage

blib/lib/Dancer2/Plugin/BeforeRoute.pm
Criterion Covered Total %
statement 51 51 100.0
branch 30 30 100.0
condition n/a
subroutine 9 9 100.0
pod 0 1 0.0
total 90 91 98.9


line stmt bran cond sub pod time code
1              
2             =head1 NAME
3            
4             Dancer2::Plugin::BeforeRoute - A before hook for a specify route or routes
5            
6             =head1 USAGE
7              
8             use Dancer2::Plugin::BeforeRoute;
9              
10             before_route get => "/", sub {
11             var before_run => "homepage";
12             };
13              
14             before_route ["get", "post"] => "/", sub {
15             var before_run => "homepage";
16             };
17              
18             get "/" => sub {
19             ## Return "homepage"
20             return var "before_run";
21             };
22              
23             before_route get => "/foo", sub {
24             var before_run => "foo"
25             };
26              
27             get "/foo" => sub {
28             ## Return "foo"
29             return var "before_run";
30             };
31              
32             before_template_route
33              
34             =head1 DESCRIPTION
35              
36             Dancer provides hook before to do everythings before going any route.
37              
38             This plugin is to provide a little bit more specifically hook before route or route(s) executed.
39              
40             =head1 AUTHOR
41            
42             Michael Vu, C<< >>
43            
44             =head1 BUGS
45            
46             Please report any bugs or feature requests to C, or through
47             the web interface at L. I will be notified, and then you'll
48             automatically be notified of progress on your bug as I make changes.
49            
50             =head1 SUPPORT
51            
52             You can find documentation for this module with the perldoc command.
53            
54             perldoc Dancer2::Plugin::BeforeRoute
55            
56             You can also look for information at:
57            
58             =over 4
59            
60             =item * RT: CPAN's request tracker
61            
62             L
63            
64             =item * AnnoCPAN: Annotated CPAN documentation
65            
66             L
67            
68             =item * CPAN Ratings
69            
70             L
71            
72             =item * Search CPAN
73            
74             L
75            
76             =item * GIT Respority
77            
78             L
79            
80             =back
81            
82             =head1 ACKNOWLEDGEMENTS
83            
84             This program is free software; you can redistribute it and/or modify it
85             under the same terms as Perl itself.
86              
87             =cut
88              
89             package Dancer2::Plugin::BeforeRoute;
90             $Dancer2::Plugin::BeforeRoute::VERSION = '2.0';
91 5     5   1425623 use Carp qw( confess );
  5         10  
  5         253  
92 5     5   2322 use Dancer2::Plugin;
  5         304582  
  5         33  
93              
94             sub BUILD {
95 3     3 0 4261 my $plugin = shift;
96              
97 3         71 $plugin->app->add_hook(
98             Dancer2::Core::Hook->new(
99             name => "before",
100             code => \&_process_before_route_hooks,
101             )
102             );
103             }
104              
105             {
106             my @ROUTES = ();
107              
108             register before_route => sub {
109 7     7   652044 my $self = shift;
110 7         22 my ( $path, $subref, @methods ) = _args(@_);
111 7         40 push @ROUTES,
112             {
113             self => $self,
114             methods => \@methods,
115             path => $path,
116             subref => $subref,
117             };
118             };
119              
120             sub _process_before_route_hooks {
121 14     14   283972 my $app = shift;
122 14         37 ROUTE: foreach my $route (@ROUTES) {
123 30         125 my $self = $route->{self};
124             next ROUTE
125 30 100       44 if !$self->request_for( $app, $route->{path}, @{ $route->{methods} } );
  30         80  
126 10         49 $route->{subref}->($app, @_);
127             }
128             }
129             }
130              
131             register request_for => sub {
132 30     30   32 my $self = shift;
133 30         25 my $app = shift;
134 30         50 my ( $path, @methods ) = @_;
135              
136 30         99 my $request_method = $app->request->method;
137 30         152 my $request_path = $app->request->path_info;
138              
139             # Shared portion of the log message,
140             # for both when the request matches and when it does not.
141 30         97 my $match_message = q{};
142              
143             grep {
144 30         31 $match_message = "'$request_method $request_path' against '$_ $path'";
  34         262  
145              
146             # Mismatches only logged at debug to remove excessive log volume.
147 34         88 $self->debug("Trying to match $match_message");
148             } @methods;
149              
150 30 100       1731 if ( !_is_the_right_method( $request_method, @methods ) ) {
151 6         18 return;
152             }
153              
154 24 100       56 if ( !_is_the_right_path( $request_path, $path ) ) {
155 14         65 return;
156             }
157              
158 10         49 $self->info("Matched $match_message --> got 1");
159              
160 10         577 return 1;
161             };
162              
163             sub _args {
164 12 100   12   3140 my $methods = shift
165             or confess "dev: missing method\n";
166              
167 11 100       38 my @methods = ref $methods ? @$methods : ($methods);
168              
169 11 100       126 my $path = shift
170             or confess "dev: missing path\n";
171 10 100       180 my $subref = shift
172             or confess "dev: missing a subref -> [[ @methods: $path ]]\n";
173              
174 9         23 return ( $path, $subref, @methods );
175             }
176              
177             sub _is_the_right_method {
178 30     30   32 my $method = shift;
179 30 100       80 if ( $method eq "HEAD" ) {
180 1         2 $method = "get";
181             }
182 30         42 my @methods = @_;
183 30 100       34 return ( grep { ( lc($_) eq "any" ) || /^\Q$method\E$/i } @methods )
  34 100       262  
184             ? 1
185             : 0;
186             }
187              
188             sub _is_the_right_path {
189 24     24   28 my $got_path = shift;
190 24         22 my $expected_path = shift;
191 24 100       45 if ( ref $expected_path ) {
192 5 100       21 return $got_path =~ /$expected_path/ ? 1 : 0;
193             }
194 19 100       46 if ( $expected_path =~ /\:/ ) {
195 3         10 $expected_path =~ s/\:[^\/]+/[^\/]+/g;
196 3 100       26 return $got_path =~ /^$expected_path$/ ? 1 : 0;
197             }
198 16 100       56 return $got_path eq $expected_path ? 1 : 0;
199             }
200              
201             register_plugin;