Apache-PAR
view release on metacpan or search on metacpan
PAR/Static.pm view on Meta::CPAN
use 5.005;
use strict;
# for version detection
require mod_perl;
# constants
use vars qw($CACHE_FILE $CACHE_MEMORY $CACHE_SHARED);
$CACHE_FILE = 'file';
$CACHE_MEMORY = 'memory';
$CACHE_SHARED = 'shared';
# Exporter
require Exporter;
use vars qw(@ISA %EXPORT_TAGS @EXPORT_OK @EXPORT $VERSION);
@ISA = qw(Exporter);
%EXPORT_TAGS = ( 'all' => [ qw($CACHE_FILE $CACHE_MEMORY $CACHE_SHARED) ] );
@EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
@EXPORT = qw( );
$VERSION = '0.30';
unless ($mod_perl::VERSION < 1.99) {
require Apache::Const;
import Apache::Const qw(OK NOT_FOUND FORBIDDEN);
require Apache::Response;
require Apache::RequestRec;
require Apache::RequestIO;
require Apache::RequestUtil;
require APR::Table;
}
else {
require Apache::Constants;
import Apache::Constants qw(OK NOT_FOUND FORBIDDEN);
require Apache::Log;
require Apache::File;
}
use MIME::Types ();
use Archive::Zip ();
sub handler {
my $r = shift;
my $filename = $r->filename;
(my $path_info = $r->path_info) =~ s/^\///;
my $file_path = $r->dir_config->get('PARStaticFilesPath') || 'htdocs/';
$file_path .= '/' if ($file_path !~ /\/$/);
$file_path .= $path_info;
$file_path =~ s/^\///;
return NOT_FOUND() unless -r $filename;
# Use the last modified time of the PAR archive
# Can cause cache to reload more often than necessary
# but much faster than opening the archive every time
my $last_modified = (stat(_))[9];
# Initialize the cache
my $cache_obj = _init_cache($r);
my $contents = _get_cache($r, $filename, $file_path, $last_modified, $cache_obj);
unless (defined $contents) {
Archive::Zip::setErrorHandler(sub {});
my $zip = Archive::Zip->new($filename);
return NOT_FOUND() unless(defined($zip));
my $member = $zip->memberNamed($file_path) || $zip->memberNamed("$file_path/");
return NOT_FOUND() unless(defined($member));
if($member->isDirectory()) {
my @index_list = $r->dir_config->get('PARStaticDirectoryIndex');
unless (@index_list) {
$r->log_error('Apache::PAR::Static: Cannot serve directory - set PARStaticDirectoryIndex to enable');
return FORBIDDEN();
}
# save $file_path for later
my $index_path = $file_path;
$index_path =~ s/\/$//;
foreach my $index_name (@index_list) {
if(defined($member = $zip->memberNamed("$index_path/$index_name"))) {
$index_path .= "/$index_name";
last;
}
}
if(!defined($member) || $member->isDirectory()) {
$r->log_error('Apache::PAR::Static: Cannot serve directory - Index file does not exist.');
return FORBIDDEN();
}
}
$contents = $member->contents;
return NOT_FOUND() unless defined($contents);
# This uses the original file name (not index name)
# Can cause a duplicate cache entry, but avoids
# having to open the archive each time to see if request
# is for a directory
_set_cache($r, $filename, $file_path, $contents, $last_modified, $cache_obj);
}
$r->headers_out->set('Accept-Ranges' => 'bytes');
$r->content_type(MIME::Types::by_suffix($file_path)->[0] || $r->dir_config->get('PARStaticDefaultMIME') || 'text/plain');
(my $package = __PACKAGE__) =~ s/::/\//g;
$r->update_mtime($last_modified);
$r->update_mtime((stat $INC{"$package.pm"})[9]);
$r->set_last_modified;
$r->set_content_length(length($contents));
if((my $status = $r->meets_conditions) eq OK()) {
$r->send_http_header if ($mod_perl::VERSION < 1.99);
}
else {
( run in 2.896 seconds using v1.01-cache-2.11-cpan-d8267643d1d )