package Plack::App::Path::Router::Custom; BEGIN { $Plack::App::Path::Router::Custom::AUTHORITY = 'cpan:STEVAN'; } { $Plack::App::Path::Router::Custom::VERSION = '0.05'; } use Moose 0.90; use MooseX::NonMoose 0.07; # ABSTRACT: A Plack component for dispatching with Path::Router extends 'Plack::Component'; has 'router' => ( is => 'ro', isa => 'Path::Router', required => 1, ); has new_request => ( traits => ['Code'], isa => 'CodeRef', default => sub { sub { $_[0] } }, handles => { new_request => 'execute', }, ); has target_to_app => ( traits => ['Code'], isa => 'CodeRef', default => sub { sub { $_[0] } }, handles => { target_to_app => 'execute', }, ); has handle_response => ( traits => ['Code'], isa => 'CodeRef', default => sub { sub { $_[0] } }, handles => { handle_response => 'execute', }, ); sub call { my ($self, $env) = @_; $env->{'plack.router'} = $self->router; my $req = $self->new_request( $env ); my $match = $self->router->match( $env->{PATH_INFO} ); if ( $match ) { $env->{'plack.router.match'} = $match; my $route = $match->route; my $mapping = $match->mapping; my @args; foreach my $component ( @{ $route->components } ) { my $name = $route->get_component_name( $component ); next unless $name; if (my $value = $mapping->{ $name }) { push @args => $value; $env->{ ('plack.router.match.args.' . $name) } = $value; } } $env->{ 'plack.router.match.args' } = \@args; my $target = $match->target; my $app = $self->target_to_app( $target ); my $res = $app->( $req, @args ); return $self->handle_response( $res, $req ); } return [ 404, [ 'Content-Type' => 'text/html' ], [ 'Not Found' ] ]; } __PACKAGE__->meta->make_immutable; no Moose; 1; __END__ =pod =head1 NAME Plack::App::Path::Router::Custom - A Plack component for dispatching with Path::Router =head1 VERSION version 0.05 =head1 SYNOPSIS use Plack::App::Path::Router::Custom; use Path::Router; my $router = Path::Router->new; $router->add_route('/' => target => sub { my ($request) = @_; # use the Plack::Request to # create a Plack::Response ... my $response = $request->new_response( 200 ); $response->content_type('text/html'); $response->body('
HELLO WORLD'); } ); $router->add_route('/:action/?:id' => validations => { id => 'Int' }, target => sub { # matches are passed to the target sub ... my ($request, $action, $id) = @_; # return a PSGI response ... [ 200, [ 'Content-Type' => 'text/html' ], [ '', $action, $id, '' ] ] } ); $router->add_route('/:action/edit/:id' => validations => { id => 'Int' }, target => sub { my ($r, $action, $id) = @_; # return a string (we will wrap # it in a PSGI response for you) "This is my action($action), and I am editing this id($id)"; } ); $router->add_route('/foo' => # target objects are also supported # as long as the object responds to # the ->execute method target => MyApp::Action->new( type => 'FOO' ) ); # now create the Plack app my $app = Plack::App::Path::Router::Custom->new( router => $router, new_request => sub { my ($env) = @_; Plack::Request->new($env) }, target_to_app => sub { my ($target) = @_; blessed($target) && $target->can('execute') ? sub { $target->execute(@_) } : $target }, handle_response => sub { my ($res, $req) = @_; if (!ref($res)) { return [ 200, [], [$res] ]; } elsif (blessed($res) && $res->can('finalize')) { return $res->finalize; } else { return $res; } }, ); =head1 DESCRIPTION This is a L