X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FPlugin%2FStatic%2FSimple.pm;h=34bf11177b2e13bd1309b1d71ea098d5ce86c7b9;hb=fa25e42244238fc2159263a05d7cffe9e0ac9557;hp=719a4708774ec09057f9a87500bdf04591647cb0;hpb=7e7cdb8e775b76d8ac27830bba82287900bd5ecf;p=catagits%2FCatalyst-Plugin-Static-Simple.git diff --git a/lib/Catalyst/Plugin/Static/Simple.pm b/lib/Catalyst/Plugin/Static/Simple.pm index 719a470..34bf111 100644 --- a/lib/Catalyst/Plugin/Static/Simple.pm +++ b/lib/Catalyst/Plugin/Static/Simple.pm @@ -1,22 +1,23 @@ package Catalyst::Plugin::Static::Simple; -use strict; -use warnings; -use base qw/Class::Accessor::Fast Class::Data::Inheritable/; +use Moose::Role; use File::stat; use File::Spec (); use IO::File (); use MIME::Types (); -use MRO::Compat; +use MooseX::Types::Moose qw/ArrayRef Str/; +use Catalyst::Utils; +use namespace::autoclean; -our $VERSION = '0.26'; +our $VERSION = '0.30'; -__PACKAGE__->mk_accessors( qw/_static_file _static_debug_message/ ); +has _static_file => ( is => 'rw' ); +has _static_debug_message => ( is => 'rw', isa => ArrayRef[Str] ); -sub prepare_action { +before prepare_action => sub { my $c = shift; my $path = $c->req->path; - my $config = $c->config->{static}; + my $config = $c->config->{'Plugin::Static::Simple'}; $path =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg; @@ -58,43 +59,46 @@ sub prepare_action { # and does it exist? $c->_locate_static_file( $path ); } +}; - return $c->next::method(@_); -} - -sub dispatch { +around dispatch => sub { + my $orig = shift; my $c = shift; return if ( $c->res->status != 200 ); if ( $c->_static_file ) { - if ( $c->config->{static}{no_logs} && $c->log->can('abort') ) { + if ( $c->config->{'Plugin::Static::Simple'}->{no_logs} && $c->log->can('abort') ) { $c->log->abort( 1 ); } return $c->_serve_static; } else { - return $c->next::method(@_); + return $c->$orig(@_); } -} +}; -sub finalize { +before finalize => sub { my $c = shift; # display all log messages - if ( $c->config->{static}{debug} && scalar @{$c->_debug_msg} ) { + if ( $c->config->{'Plugin::Static::Simple'}->{debug} && scalar @{$c->_debug_msg} ) { $c->log->debug( 'Static::Simple: ' . join q{ }, @{$c->_debug_msg} ); } +}; - return $c->next::method(@_); -} - -sub setup { +before setup_finalize => sub { my $c = shift; - $c->maybe::next::method(@_); - - my $config = $c->config->{static} ||= {}; + $c->log->warn("Deprecated 'static' config key used, please use the key 'Plugin::Static::Simple' instead") + if exists $c->config->{static}; + my $config + = $c->config->{'Plugin::Static::Simple'} + = $c->config->{'static'} + = Catalyst::Utils::merge_hashes( + $c->config->{'Plugin::Static::Simple'} || {}, + $c->config->{static} || {} + ); $config->{dirs} ||= []; $config->{include_path} ||= [ $c->config->{root} ]; @@ -111,7 +115,7 @@ sub setup { # preload the type index hash so it's not built on the first request $config->{mime_types_obj}->create_type_index; -} +}; # Search through all included directories for the static file # Based on Template Toolkit INCLUDE_PATH code @@ -122,7 +126,7 @@ sub _locate_static_file { File::Spec->no_upwards( File::Spec->splitdir( $path ) ) ); - my $config = $c->config->{static}; + my $config = $c->config->{'Plugin::Static::Simple'}; my @ipaths = @{ $config->{include_path} }; my $dpaths; my $count = 64; # maximum number of directories to search @@ -177,6 +181,7 @@ sub _locate_static_file { sub _serve_static { my $c = shift; + my $config = $c->config->{'Plugin::Static::Simple'}; my $full_path = shift || $c->_static_file; my $type = $c->_ext_to_type( $full_path ); @@ -185,6 +190,12 @@ sub _serve_static { $c->res->headers->content_type( $type ); $c->res->headers->content_length( $stat->size ); $c->res->headers->last_modified( $stat->mtime ); + # Tell Firefox & friends its OK to cache, even over SSL: + $c->res->headers->header('Cache-control' => 'public'); + # Optionally, set a fixed expiry time: + if ($config->{expires}) { + $c->res->headers->expires(time() + $config->{expires}); + } my $fh = IO::File->new( $full_path, 'r' ); if ( defined $fh ) { @@ -202,7 +213,7 @@ sub _serve_static { sub serve_static_file { my ( $c, $full_path ) = @_; - my $config = $c->config->{static} ||= {}; + my $config = $c->config->{'Plugin::Static::Simple'}; if ( -e $full_path ) { $c->_debug_msg( "Serving static file: $full_path" ) @@ -223,7 +234,7 @@ sub serve_static_file { sub _ext_to_type { my ( $c, $full_path ) = @_; - my $config = $c->config->{static}; + my $config = $c->config->{'Plugin::Static::Simple'}; if ( $full_path =~ /.*\.(\S{1,})$/xms ) { my $ext = $1; @@ -301,7 +312,7 @@ C<404> error if your applicaton can not process the request: # handled by static::simple, not dispatched to your application /images/exists.png - + # static::simple will not find the file and let your application # handle the request. You are responsible for generating a file # or returning a 404 error @@ -312,7 +323,7 @@ the operation by adding various configuration options. In a production environment, you will probably want to use your webserver to deliver static content; for an example see L, below. -=head1 DEFAULT BEHAVIOR +=head1 DEFAULT BEHAVIOUR By default, Static::Simple will deliver all files having extensions (that is, bits of text following a period (C<.>)), I files @@ -334,7 +345,7 @@ Logging of static files is turned off by default. =head1 ADVANCED CONFIGURATION Configuration is completely optional and is specified within -Cconfig-E{static}>. If you use any of these options, +Cconfig-E{Plugin::Static::Simple}>. If you use any of these options, this module will probably feel less "simple" to you! =head2 Enabling request logging @@ -343,7 +354,7 @@ Since Catalyst 5.50, logging of static requests is turned off by default; static requests tend to clutter the log output and rarely reveal anything useful. However, if you want to enable logging of static requests, you can do so by setting -Cconfig-E{static}-E{logging}> to 1. +Cconfig-E{Plugin::Static::Simple}-E{logging}> to 1. =head2 Forcing directories into static mode @@ -351,10 +362,14 @@ Define a list of top-level directories beneath your 'root' directory that should always be served in static mode. Regular expressions may be specified using C. - MyApp->config->{static}->{dirs} = [ - 'static', - qr/^(images|css)/, - ]; + MyApp->config( + 'Plugin::Static::Simple' => { + dirs => [ + 'static', + qr/^(images|css)/, + ], + } + ); =head2 Including additional directories @@ -364,11 +379,15 @@ first file found. Note that your root directory is B automatically added to the search path when you specify an C. You should use Cconfig-E{root}> to add it. - MyApp->config->{static}->{include_path} = [ - '/path/to/overlay', - \&incpath_generator, - MyApp->config->{root} - ]; + MyApp->config( + 'Plugin::Static::Simple' => { + include_path => [ + '/path/to/overlay', + \&incpath_generator, + MyApp->config->{root}, + ], + }, + ); With the above setting, a request for the file C will search for the following files, returning the first one found: @@ -387,7 +406,7 @@ For example: sub incpath_generator { my $c = shift; - + if ( $c->session->{customer_dir} ) { return [ $c->session->{customer_dir} ]; } else { @@ -404,8 +423,11 @@ C will be ignored by Static::Simple in the interest of security. If you wish to define your own extensions to ignore, use the C option: - MyApp->config->{static}->{ignore_extensions} - = [ qw/html asp php/ ]; + MyApp->config( + 'Plugin::Static::Simple' => { + ignore_extensions => [ qw/html asp php/ ], + }, + ); =head2 Ignoring entire directories @@ -414,7 +436,11 @@ the C option. This option contains a list of relative directory paths to ignore. If using C, the path will be checked against every included path. - MyApp->config->{static}->{ignore_dirs} = [ qw/tmpl css/ ]; + MyApp->config( + 'Plugin::Static::Simple' => { + ignore_dirs => [ qw/tmpl css/ ], + }, + ); For example, if combined with the above C setting, this C value will ignore the following directories if they exist: @@ -431,10 +457,31 @@ C value will ignore the following directories if they exist: To override or add to the default MIME types set by the L module, you may enter your own extension to MIME type mapping. - MyApp->config->{static}->{mime_types} = { - jpg => 'image/jpg', - png => 'image/png', - }; + MyApp->config( + 'Plugin::Static::Simple' => { + mime_types => { + jpg => 'image/jpg', + png => 'image/png', + }, + }, + ); + +=head2 Controlling caching with Expires header + +The files served by Static::Simple will have a Last-Modified header set, +which allows some browsers to cache them for a while. However if you want +to explicitly set an Expires header, such as to allow proxies to cache your +static content, then you can do so by setting the "expires" config option. + +The value indicates the number of seconds after access time to allow caching. +So a value of zero really means "don't cache at all", and any higher values +will keep the file around for that long. + + MyApp->config( + 'Plugin::Static::Simple' => { + expires => 3600, # Caching allowed for one hour. + }, + ); =head2 Compatibility with other plugins @@ -447,7 +494,11 @@ many compatibility issues with other plugins. Enable additional debugging information printed in the Catalyst log. This is automatically enabled when running Catalyst in -Debug mode. - MyApp->config->{static}->{debug} = 1; + MyApp->config( + 'Plugin::Static::Simple' => { + debug => 1, + }, + ); =head1 USING WITH APACHE @@ -552,6 +603,10 @@ Tomas Doran, Justin Wheeler (dnm) +Matt S Trout, + +Toby Corkindale, + =head1 THANKS The authors of Catalyst::Plugin::Static: @@ -566,7 +621,7 @@ For the include_path code from Template Toolkit: =head1 COPYRIGHT -Copyright (c) 2005 - 2009 +Copyright (c) 2005 - 2011 the Catalyst::Plugin::Static::Simple L and L as listed above.