Catalyst-Plugin-URLMap

 view release on metacpan or  search on metacpan

lib/Catalyst/Plugin/URLMap.pm  view on Meta::CPAN

package Catalyst::Plugin::URLMap;

use Moose::Role;
use namespace::autoclean;
use Plack::Util;
use Plack::App::URLMap;
use Scalar::Util 'blessed', 'weaken';
use Catalyst::Utils;
use Text::SimpleTable;

our $VERSION = '0.002';

my $from_plack_app = sub {
  my $app = shift;
  if($app->can('to_app')) {
    return $app->to_app;
  } elsif($app->can('psgi_app')) {
    return $app->psgi_app;
  } else {
    die ref($app). " is not a plack compatible application";
  }
};

my ($do_mapping, $weakened_do_mapping);
$do_mapping = $weakened_do_mapping = sub {
  my ($psgi_app, $t, $root, %maps) = @_;

  foreach my $url_part (keys %maps) {
    my $target = $maps{$url_part};
    my $map_url = join ('', $root, $url_part);

    if(ref $target eq 'CODE') {
      $psgi_app->map($url_part, $target);
      $t->row($map_url, 'CODE');
    } elsif(blessed $target) {
      $psgi_app->map($url_part, $from_plack_app->($target));
      $t->row($map_url, ref $target);
    } elsif(ref $target eq 'HASH') {
      if( (%$target)[0] =~m/^\//) {
        my $localmap = Plack::App::URLMap->new;
        weaken $weakened_do_mapping;
        $localmap = $weakened_do_mapping->($localmap, $t, $map_url, %$target);
        $psgi_app->map($url_part, $localmap->to_app);
      } else {
        my ($module, $args) = %{$target};
        my $normalized_module = Plack::Util::load_class($module, 'Plack::App');
        $psgi_app->map($url_part, $from_plack_app->($normalized_module->new(%$args)));
        $t->row($map_url, $normalized_module);
      }
    } elsif($target) {
      my $normalized_module = Plack::Util::load_class($target, 'Plack::App');
      $psgi_app->map($url_part, $from_plack_app->($normalized_module->new));
      $t->row($map_url, $normalized_module);
    } else {
      die "I don't know how to map $target to $map_url";
    }
  }

  return $psgi_app;
};

around 'psgi_app', sub {
  my ($orig, $self, @args) = @_;
  my $psgi_app = $self->$orig(@args);
  return $psgi_app unless $self->config->{'Plugin::URLMap'};

  my %maps = %{$self->config->{'Plugin::URLMap'}};
  (my $mapped_app = Plack::App::URLMap->new)
    ->map('/' => $psgi_app);

  my $column_width = Catalyst::Utils::term_width() - 49;
  my $t = Text::SimpleTable->new([40, 'Path'], [$column_width, 'Application']);
  my $app =  $do_mapping->($mapped_app, $t, '', %maps)->to_app;

  if ($self->debug) {
    $self->log->debug( "Loaded Plack Middleware:\n" . $t->draw . "\n" );
  }

  return $app;
};

1;

=head1 NAME

Catalyst::Plugin::URLMap - Mount a Plack application using Catalyst Configuration

=head1 SYNOPSIS

    package MyApp::Web;

    our $VERSION = '0.01';

    use Moose;
    use Catalyst qw/URLMap/;

    extends 'Catalyst';

    __PACKAGE__->config(
      'Plugin::URLMap',
      {



( run in 2.039 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )