AxKit2

 view release on metacpan or  search on metacpan

plugins/aio/uri_to_file  view on Meta::CPAN


This plugin provides the filename for a given URI. It is absolutely required
that you load this plugin if you wish to serve files off the filesystem, or else
re-implement its functionality somehow.

It also splits off the path_info off the URI, provides a redirect when a
directory without a "/" is requested, and implements C<DirectoryIndex> (see below).

=head1 CONFIG

=head2 DirectoryIndex STRING

A filename to append to directory requests. If the file exists then it will be
the filename used instead of the directory itself.

=cut

use File::Spec::Functions qw(canonpath catfile splitdir catdir splitpath catpath);
use AxKit2::Utils qw(uri_decode);

sub register {
    my $self = shift;
    $self->register_hook('uri_translation' => 'hook_uri_translation1');
    $self->register_hook('uri_translation' => 'hook_uri_translation2');
}

sub init {
    my $self = shift;
    $self->register_config('DirectoryIndex', sub { $self->set_dirindex(@_) });
}

sub set_dirindex {
    my ($self, $config, $value) = @_;
    my $key = $self->plugin_name . '::dirindex';
    $config->notes($key, $value);
}

sub hook_uri_translation1 {
    my ($self, $hd, $uri) = @_;
    
    $self->log(LOGINFO, "translate: $uri");
    
    $uri =~ s/\?.*//;
    my $original_uri = $uri;
    
    $uri = uri_decode($uri);
    
    if ($uri =~ /\.\./) {
        return BAD_REQUEST;
    }
    
    my $root = $self->config->path;
    
    $uri =~ s/^\Q$root// || die "$uri did not match config path $root";
    
    my ($volume, $dir, $file) = splitpath($self->config->docroot, 1);
    my @path = (splitdir($dir),split(/\//,$uri));

    my $i = -1;

    # save these so they get locked in for the closure.
    my $client   = $self->client;
    my $config   = $self->config;
    my $dirindex = $self->config('dirindex');

# $self->log(LOGCRIT, __LINE__ . " ...");
    IO::AIO::aio_stat(catpath($volume,catdir(@path),''), sub {
        if (-d _) {
            $i = @path-1;
            if ($original_uri =~ m/\/$/) {
                if (defined $dirindex) {
                    my $filepath = catpath($volume, catdir(@path), $dirindex);
                    IO::AIO::aio_stat($filepath, sub {
                        if (-f _) {
                            push @path, $dirindex;
                        }
                        $self->setup_paths($hd, $volume, \@path, $i, $uri, $original_uri);
                        return $client->finish_continuation;
                    });
                }
            }
            else {
                $client->notes('need_redirect', 1);
                $self->setup_paths($hd, $volume, \@path, $i, $uri, $original_uri);
                return $client->finish_continuation;
            }
        }
        else {
            my $path = '';
            my $sub;
            $i = $#path;
            $sub = sub {
                if ($i == 0) {
                    $self->setup_paths($hd, $volume, \@path, $i, $uri, $original_uri);
                    return $client->finish_continuation;
                }
                if ($path && -e _) {
                    # entity exists
                    $i++ if -d _;
                    $self->setup_paths($hd, $volume, \@path, $i, $uri, $original_uri);
                    return $client->finish_continuation;
                }
                $i--;
                $path = catdir(@path[0..$i+1]);
                IO::AIO::aio_stat(catpath($volume, $path, ''), $sub);
            };
            $sub->();
        }
    });
    
    return CONTINUATION;
}

sub setup_paths {
    my $self = shift;
    my ($hd, $volume, $paths, $i, $uri, $original_uri) = @_;
    
    $hd->filename(
        canonpath(
            catpath(
                $volume,



( run in 0.444 second using v1.01-cache-2.11-cpan-e1769b4cff6 )