Plack-App-Directory-Template
view release on metacpan or search on metacpan
lib/Plack/App/Directory/Template.pm view on Meta::CPAN
use strict;
use warnings;
package Plack::App::Directory::Template;
#ABSTRACT: Serve static files from document root with directory index template
our $VERSION = '0.27'; #VERSION
use v5.10;
use parent qw(Plack::App::Directory);
use Plack::Middleware::TemplateToolkit;
use Plack::Util::Accessor qw(filter templates);
use File::ShareDir qw(dist_dir);
use File::stat;
use DirHandle;
use Cwd qw(abs_path);
use URI::Escape;
sub prepare_app {
my $self = shift;
$self->{_default_vars} = delete $self->{VARIABLES} // { };
$self->{templates} = delete $self->{INCLUDE_PATH} if $self->{INCLUDE_PATH};
}
sub serve_path {
my($self, $env, $dir, $fullpath) = @_;
if (-f $dir) {
return $self->SUPER::serve_path($env, $dir, $fullpath);
}
if (defined $self->{dir_index}) {
my $index_file = "$dir/".$self->{dir_index};
if (-f $index_file) {
return $self->SUPER::serve_path($env, $index_file, $fullpath);
}
}
my $urlpath = $env->{SCRIPT_NAME} . $env->{PATH_INFO};
if ($urlpath !~ m{/$}) {
return $self->return_dir_redirect($env);
}
$urlpath = join('/', map {uri_escape($_)} split m{/}, $urlpath).'/';
my $dh = DirHandle->new($dir);
my @children;
while (defined(my $ent = $dh->read)) {
next if $ent eq '.' or $ent eq '..';
push @children, $ent;
}
my $files = [ ];
my @special = ('.');
push @special, '..' if $env->{PATH_INFO} ne '/';
foreach ( @special, sort { $a cmp $b } @children ) {
my $name = $_;
my $file = "$dir/$_";
my $stat = stat($file);
my $url = $urlpath . uri_escape($_);
my $is_dir = -d $file; # TODO: use Fcntl instead ?
push @$files, bless {
name => $is_dir ? "$name/" : $name,
url => $is_dir ? "$url/" : $url,
mime_type => $is_dir ? 'directory' : ( Plack::MIME->mime_type($file) || 'text/plain' ),
stat => $stat,
}, 'Plack::App::Directory::Template::File';
}
$files = [ map { $self->filter->($_) || () } @$files ] if $self->filter;
my $default_vars = {
%{ $self->{_default_vars} },
path => $env->{PATH_INFO},
urlpath => $urlpath,
root => abs_path($self->root),
dir => abs_path($dir),
};
my $tt_vars = $self->template_vars( %$default_vars, files => $files );
if ($env->{'tt.vars'}) {
$env->{'tt.vars'}->{$_} = $tt_vars->{$_} for keys %$tt_vars;
} else {
$env->{'tt.vars'} = $tt_vars;
}
$env->{'tt.template'} = ref $self->templates ? $self->templates
: ($self->{PROCESS} // 'index.html');
$self->{tt} //= Plack::Middleware::TemplateToolkit->new(
INCLUDE_PATH => $self->templates
// eval { dist_dir('Plack-App-Directory-Template') }
// 'share',
VARIABLES => $default_vars,
request_vars => [qw(scheme base parameters path user)],
map { $_ => $self->{$_} } grep { $_ =~ /^[A-Z_]+$/ } keys %$self
)->to_app;
return $self->{tt}->($env);
}
( run in 0.989 second using v1.01-cache-2.11-cpan-71847e10f99 )