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