File Coverage

blib/lib/Dancer2/Core/Dispatcher.pm
Criterion Covered Total %
statement 31 31 100.0
branch 4 4 100.0
condition n/a
subroutine 6 6 100.0
pod 1 1 100.0
total 42 42 100.0


line stmt bran cond sub pod time code
1             # ABSTRACT: Class for dispatching request to the appropriate route handler
2             $Dancer2::Core::Dispatcher::VERSION = '0.400000';
3             use Moo;
4 140     140   1007  
  140         341  
  140         972  
5             use Dancer2::Core::Types;
6 140     140   44275 use Dancer2::Core::Request;
  140         380  
  140         958  
7 140     140   1127652 use Dancer2::Core::Response;
  140         343  
  140         3730  
8 140     140   64519  
  140         474  
  140         43715  
9             has apps => (
10             is => 'rw',
11             isa => ArrayRef,
12             default => sub { [] },
13             );
14              
15             has apps_psgi => (
16             is => 'ro',
17             isa => ArrayRef,
18             lazy => 1,
19             builder => '_build_apps_psgi',
20             );
21              
22             my $self = shift;
23             return [ map +( $_->name, $_->to_app ), @{ $self->apps } ];
24 33     33   454 }
25 33         70  
  33         517  
26             my ( $self, $env ) = @_;
27             my @apps = @{ $self->apps_psgi };
28              
29 118     118 1 28685 DISPATCH: while (1) {
30 118         197 for ( my $i = 0; $i < @apps; $i += 2 ) {
  118         2477  
31             my ( $app_name, $app ) = @apps[ $i, $i + 1 ];
32 118         1099  
33 135         458 my $response = $app->($env);
34 177         484  
35             # check for an internal request
36 177         516 delete Dancer2->runner->{'internal_forward'}
37             and next DISPATCH;
38              
39 177 100       7160 # the app raised a flag saying it couldn't match anything
40             # which is different than "I matched and it's a 404"
41             delete Dancer2->runner->{'internal_404'}
42             or do {
43             delete Dancer2->runner->{'internal_request'};
44             return $response;
45 160 100       371 };
46 109         239 }
47 109         463  
48             # don't run anymore
49             delete Dancer2->runner->{'internal_request'};
50             last;
51             } # while
52 9         28  
53 9         97 # a 404 on all apps, using the first app
54             my $default_app = $self->apps->[0];
55             my $request = $default_app->build_request($env);
56             return $default_app->response_not_found($request)->to_psgi;
57 9         175 }
58 9         76  
59 9         34 1;
60              
61              
62             =pod
63              
64             =encoding UTF-8
65              
66             =head1 NAME
67              
68             Dancer2::Core::Dispatcher - Class for dispatching request to the appropriate route handler
69              
70             =head1 VERSION
71              
72             version 0.400000
73              
74             =head1 SYNOPSIS
75              
76             use Dancer2::Core::Dispatcher;
77              
78             # Create an instance of dispatcher
79             my $dispatcher = Dancer2::Core::Dispatcher->new( apps => [$app] );
80              
81             # Dispatch a request
82             my $resp = $dispatcher->dispatch($env)->to_psgi;
83              
84             # Capture internal error of a response (if any) after a dispatch
85             $dispatcher->response_internal_error($app, $error);
86              
87             # Capture response not found for an application the after dispatch
88             $dispatcher->response_not_found($env);
89              
90             =head1 ATTRIBUTES
91              
92             =head2 apps
93              
94             The apps is an array reference to L<Dancer2::Core::App>.
95              
96             =head2 default_content_type
97              
98             The default_content_type is a string which represents the context of the
99             request. This attribute is read-only.
100              
101             =head1 METHODS
102              
103             =head2 dispatch
104              
105             The C<dispatch> method accepts the list of applications, hash reference for
106             the B<env> attribute of L<Dancer2::Core::Request> and optionally the request
107             object and an env as input arguments.
108              
109             C<dispatch> returns a response object of L<Dancer2::Core::Response>.
110              
111             Any before hook and matched route code is wrapped to allow DSL keywords such
112             as forward and redirect to short-circuit remaining code, returning across
113             multiple stack frames without having to throw an exception.
114              
115             =head2 response_internal_error
116              
117             The C<response_internal_error> takes as input the list of applications and
118             a variable error and returns an object of L<Dancer2::Core::Error>.
119              
120             =head2 response_not_found
121              
122             The C<response_not_found> consumes as input the list of applications and an
123             object of type L<Dancer2::Core::App> and returns an object
124             L<Dancer2::Core::Error>.
125              
126             =head1 AUTHOR
127              
128             Dancer Core Developers
129              
130             =head1 COPYRIGHT AND LICENSE
131              
132             This software is copyright (c) 2022 by Alexis Sukrieh.
133              
134             This is free software; you can redistribute it and/or modify it under
135             the same terms as the Perl 5 programming language system itself.
136              
137             =cut