[Catalyst-commits] r6668 - in trunk/Catalyst-Plugin-PageCache: lib/Catalyst/Plugin t

jshirley at dev.catalyst.perl.org jshirley at dev.catalyst.perl.org
Wed Aug 15 20:56:35 GMT 2007


Author: jshirley
Date: 2007-08-15 20:56:34 +0100 (Wed, 15 Aug 2007)
New Revision: 6668

Added:
   trunk/Catalyst-Plugin-PageCache/t/13cachehook.t
Modified:
   trunk/Catalyst-Plugin-PageCache/lib/Catalyst/Plugin/PageCache.pm
Log:
Adding cache_hook config param to use a method call to determine whether a page can be cached.  Some pod formatting cleanup as well.

Modified: trunk/Catalyst-Plugin-PageCache/lib/Catalyst/Plugin/PageCache.pm
===================================================================
--- trunk/Catalyst-Plugin-PageCache/lib/Catalyst/Plugin/PageCache.pm	2007-08-15 19:10:43 UTC (rev 6667)
+++ trunk/Catalyst-Plugin-PageCache/lib/Catalyst/Plugin/PageCache.pm	2007-08-15 19:56:34 UTC (rev 6668)
@@ -74,6 +74,10 @@
     # never serve POST request pages from cache
     return $c->NEXT::dispatch(@_) if ( $c->req->method eq "POST" );
 
+    my $hook = $c->config->{page_cache}->{cache_hook} ?
+        $c->can($c->config->{page_cache}->{cache_hook}) : undef;
+    return $c->NEXT::dispatch(@_) if ( $hook && !$c->$hook() );
+
     return $c->NEXT::dispatch(@_) if (
         $c->config->{page_cache}->{auto_check_user} &&
         $c->can('user_exists') &&
@@ -193,6 +197,12 @@
 
     # never cache POST requests
     return $c->NEXT::finalize(@_) if ( $c->req->method eq "POST" );
+
+    my $hook = $c->config->{page_cache}->{cache_hook} ?
+        $c->can($c->config->{page_cache}->{cache_hook}) : undef;
+    return $c->NEXT::finalize(@_) if ( $hook && !$c->$hook() );
+
+
     return $c->NEXT::finalize(@_) if (
         $c->config->{page_cache}->{auto_check_user} &&
         $c->can('user_exists') &&
@@ -355,7 +365,19 @@
             '/list',
         ],
         debug => 1,
+        # Optionally, a cache hook to be called prior to dispatch to
+        # determine if the page should be cached.  This is called both
+        # before dispatch, and before finalize.
+        cache_hook => 'some_method'
     };
+    
+    sub some_method {
+        my ( $c ) = @_;
+        if ( $c->user_exists and $c->user->some_field ) {
+            return 0; # Don't cache
+        }
+        return 1; # Cache
+    }
 
     # in a controller method
     $c->cache_page( '3600' );
@@ -376,30 +398,30 @@
 
 =head1 DESCRIPTION
 
-Many dynamic websites perform heavy processing on most pages, yet this information
-may rarely change from request to request.  Using the PageCache plugin, you can
-cache the full output of different pages so they are served to your visitors as
-fast as possible.  This method of caching is very useful for withstanding a
-Slashdotting, for example.
+Many dynamic websites perform heavy processing on most pages, yet this
+information may rarely change from request to request.  Using the PageCache
+plugin, you can cache the full output of different pages so they are served to
+your visitors as fast as possible.  This method of caching is very useful for
+withstanding a Slashdotting, for example.
 
-This plugin requires that you also load a Cache plugin.  Please see the Known Issues
-when choosing a cache backend.
+This plugin requires that you also load a Cache plugin.  Please see the Known
+Issues when choosing a cache backend.
 
 =head1 WARNINGS
 
 PageCache should be placed at the end of your plugin list.
 
 You should only use the page cache on pages which have NO user-specific or
-customized content.  Also, be careful if caching a page which may forward to another
-controller.  For example, if you cache a page behind a login screen, the logged-in
-version may be cached and served to unauthenticated users.
+customized content.  Also, be careful if caching a page which may forward to
+another controller.  For example, if you cache a page behind a login screen,
+the logged-in version may be cached and served to unauthenticated users.
 
 Note that pages that result from POST requests will never be cached.
 
 =head1 PERFORMANCE
 
-On my Athlon XP 1800+ Linux server, a cached page is served in 0.008 seconds when
-using the HTTP::Daemon server and any of the Cache plugins.
+On my Athlon XP 1800+ Linux server, a cached page is served in 0.008 seconds
+when using the HTTP::Daemon server and any of the Cache plugins.
 
 =head1 CONFIGURATION
 
@@ -407,34 +429,56 @@
 
     expires => $seconds
 
-This will set the default expiration time for all page caches.  If you do not specify
-this, expiration defaults to 300 seconds (5 minutes).
+This will set the default expiration time for all page caches.  If you do not
+specify this, expiration defaults to 300 seconds (5 minutes).
 
     set_http_headers => 1
 
-Enabling this value will cause Catalyst to set the correct HTTP headers to allow
-browsers and proxy servers to cache your page.  This will further reduce the load on
-your server.  The headers are set in such a way that the browser/proxy cache will
-expire at the same time as your cache.  The Last-Modified header will be preserved
-if you have already specified it.
+Enabling this value will cause Catalyst to set the correct HTTP headers to
+allow browsers and proxy servers to cache your page.  This will further reduce
+the load on your server.  The headers are set in such a way that the
+browser/proxy cache will expire at the same time as your cache.  The
+Last-Modified header will be preserved if you have already specified it.
 
-
     auto_cache => [
         $uri,
     ]
 
-To automatically cache certain pages, or all pages, you can specify auto-cache URIs as
-an array reference.  Any controller within your application that matches one of the
-auto_cache URIs will be cached using the default expiration time.  URIs may be specified
-as absolute: '/list' or as a regex: '/view/.*'
+To automatically cache certain pages, or all pages, you can specify auto-cache
+URIs as an array reference.  Any controller within your application that
+matches one of the auto_cache URIs will be cached using the default expiration
+time.  URIs may be specified as absolute: '/list' or as a regex: '/view/.*'
 
     debug => 1
 
-This will print additional debugging information to the Catalyst log.  You will need to
-have -Debug enabled to see these messages.
-You can also specify an optional config parameter auto_check_user. If this
-option is enabled, automatic caching is disabled for logged in users.
+This will print additional debugging information to the Catalyst log.  You will
+need to have -Debug enabled to see these messages.  You can also specify an
+optional config parameter auto_check_user. If this option is enabled,
+automatic caching is disabled for logged in users.
 
+    cache_hook => 'cache_hook_method'
+
+Calls a method on the application that is expected to return a true or false.
+This method is called before dispatch, and before finalize so you can short
+circuit the pagecache behavior.  As an example, if you want to disable
+PageCache while running under debug mode:
+   
+    package MyApp;
+    
+    ...
+    
+    sub cache_hook_method { return shift->debug; }
+
+Or, if you want to not cache for certain roles, say "admin":
+    
+    sub cache_hook_method {
+        my ( $c ) = @_;
+        return !$c->check_user_roles('admin');
+    }
+
+Note that this is called BEFORE auto_check_user, so you have more flexibility
+to determine what to do for not logged in users.
+
 =head1 METHODS
 
 =head2 cache_page
@@ -445,9 +489,9 @@
 
 The page will be cached for $expire seconds.  Every user who visits the URI(s)
 referenced by that controller will receive the page directly from cache.  Your
-controller will not be processed again until the cache expires.  You can set this
-value to as low as 60 seconds if you have heavy traffic to greatly improve site
-performance.
+controller will not be processed again until the cache expires.  You can set
+this value to as low as 60 seconds if you have heavy traffic to greatly
+improve site performance.
 
 Pass in a DateTime object to make the cache expire at a given point in time.
 
@@ -551,9 +595,9 @@
     $c->clear_cached_page( '/view/userlist' );
     $c->clear_cached_page( '/view/.*' );
 
-This method takes an absolute path or regular expression.  For obvious reasons, this
-must be called from a different controller than the cached controller. You may for
-example wish to build an admin page that lets you clear page caches.
+This method takes an absolute path or regular expression.  For obvious reasons,
+this must be called from a different controller than the cached controller. You
+may for example wish to build an admin page that lets you clear page caches.
 
 =head1 INTERNAL EXTENDED METHODS
 
@@ -571,24 +615,26 @@
 
 =head1 I18N SUPPORT
 
-If your application uses L<Catalyst::Plugin::I18N> for localization, a separate cache
-key will be used for each language a page is displayed in.
+If your application uses L<Catalyst::Plugin::I18N> for localization, a
+separate cache key will be used for each language a page is displayed in.
 
 =head1 KNOWN ISSUES
 
-It is not currently possible to cache pages served from the Static plugin.  If you're concerned
-enough about performance to use this plugin, you should be serving static files directly from
-your web server anyway.
+It is not currently possible to cache pages served from the Static plugin.  If
+you're concerned enough about performance to use this plugin, you should be
+serving static files directly from your web server anyway.
 
-Cache::FastMmap does not have the ability to specify different expiration times for cached
-data.  Therefore, if your MyApp->config->{cache}->{expires} value is set to anything other
-than 0, you may experience problems with the clear_cached_page method, because the cache
-index may be removed.  For best results, you may wish to use Cache::FileCache or Cache::Memcached
-as your cache backend.
+Cache::FastMmap does not have the ability to specify different expiration times
+for cached data.  Therefore, if your MyApp->config->{cache}->{expires} value is
+set to anything other than 0, you may experience problems with the
+clear_cached_page method, because the cache index may be removed.  For best
+results, you may wish to use Cache::FileCache or Cache::Memcached as your cache
+backend.
 
 =head1 SEE ALSO
 
-L<Catalyst>, L<Catalyst::Plugin::Cache::FastMmap>, L<Catalyst::Plugin::Cache::FileCache>,
+L<Catalyst>, L<Catalyst::Plugin::Cache::FastMmap>,
+L<Catalyst::Plugin::Cache::FileCache>,
 L<Catalyst::Plugin::Cache::Memcached>
 
 =head1 AUTHOR

Added: trunk/Catalyst-Plugin-PageCache/t/13cachehook.t
===================================================================
--- trunk/Catalyst-Plugin-PageCache/t/13cachehook.t	                        (rev 0)
+++ trunk/Catalyst-Plugin-PageCache/t/13cachehook.t	2007-08-15 19:56:34 UTC (rev 6668)
@@ -0,0 +1,62 @@
+#!perl
+
+use strict;
+use warnings;
+no warnings 'redefine';
+
+use FindBin;
+use lib "$FindBin::Bin/lib";
+use Test::More;
+use File::Path;
+
+BEGIN {
+    eval "use Catalyst::Plugin::Cache::FileCache";
+    plan $@
+        ? ( skip_all => 'needs Catalyst::Plugin::Cache::FileCache for testing' )
+        : ( tests => 16 );
+}
+
+# This test that options can be passed to cache.
+
+# remove previous cache
+rmtree 't/var' if -d 't/var';
+
+use Catalyst::Test 'TestApp';
+
+# add config option
+TestApp->config->{page_cache}->{set_http_headers} = 1;
+TestApp->config->{page_cache}->{cache_hook}   = 'use_pagecache';
+
+local *TestApp::use_pagecache = sub { 0 };
+cmp_ok( TestApp->use_pagecache(), '==', '0' );
+
+# Load the page that can be cached, but we shouldn't cache it because of
+# use_pagecache
+ok( my $res = request('http://localhost/cache/no_cache'), 'request ok' );
+is( $res->content, 1, 'count is 1' );
+
+# Page won't be served from cache, and shouldn't have any headers
+ok( $res = request('http://localhost/cache/no_cache'), 'request ok' );
+is( $res->content, 2, 'count is 2' );
+
+isnt( $res->headers->{'cache-control'}, 'no-cache', 'cache-control header ok' );
+isnt( $res->headers->{'pragma'}, 'no-cache', 'pragma header ok' );
+ok( !$res->headers->last_modified, 'last-modified header not included' );
+
+local *TestApp::use_pagecache = sub { 1 };
+cmp_ok( TestApp->use_pagecache(), '==', '1' );
+
+# page will not be served from cache, but will be next request.
+ok( $res = request('http://localhost/cache/no_cache'), 'request ok' );
+is( $res->content, 3, 'count is 3' );
+
+# page will be served from cache and have http headers
+ok( $res = request('http://localhost/cache/no_cache'), 'request ok' );
+is( $res->content, 3, 'count is still 3' );
+
+is( $res->headers->{'cache-control'}, 'no-cache', 'cache-control header ok' );
+is( $res->headers->{'pragma'}, 'no-cache', 'pragma header ok' );
+ok( !$res->headers->last_modified, 'last-modified header not included' );
+
+
+




More information about the Catalyst-commits mailing list