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

timbunce at dev.catalyst.perl.org timbunce at dev.catalyst.perl.org
Mon Nov 1 18:43:50 GMT 2010


Author: timbunce
Date: 2010-11-01 18:43:50 +0000 (Mon, 01 Nov 2010)
New Revision: 13675

Modified:
   trunk/Catalyst-Plugin-PageCache/Changes
   trunk/Catalyst-Plugin-PageCache/Makefile.PL
   trunk/Catalyst-Plugin-PageCache/lib/Catalyst/Plugin/PageCache.pm
   trunk/Catalyst-Plugin-PageCache/t/08params.t
Log:
Use SHA1 to create cache key to limit length and charset. RT#62343.
Treat the order of repeated URL parameter values as significant.


Modified: trunk/Catalyst-Plugin-PageCache/Changes
===================================================================
--- trunk/Catalyst-Plugin-PageCache/Changes	2010-11-01 15:23:57 UTC (rev 13674)
+++ trunk/Catalyst-Plugin-PageCache/Changes	2010-11-01 18:43:50 UTC (rev 13675)
@@ -1,16 +1,18 @@
 Revision history for Perl extension Catalyst::Plugin::PageCache
 
 0.23    XXX
+        - XXX Test 15busy_lock.t fails as the moment.
         - Updated tests to use Catalyst::Plugin::Cache::Store::Memory instead
           of the deprecated ::FileCache (Report and patch from Rod Taylor) RT#53304.
         - Fixed t/04critic.t to not fail if Test::Perl::Critic is not installed.
-        - XXX Test 15busy_lock.t fails as the moment.
         - Updated test app code to avoid deprecated constructs.
         - Only serve GET and HEAD requests (instead of all except POST). RT#53307.
         - Allow key_maker to be the name of a method to be called on $c. RT#53529.
         - Assorted performance optimizations.
         - Add cache_dispatch_hook and cache_finalize_hook to config. RT#53503.
         - Refactored page cache storage logic, inspired by RT#53303.
+        - Use SHA1 to create cache key to limit length and charset. RT#62343.
+        - Treat the order of repeated URL parameter values as significant.
 
 0.22    2009-06-25 10:38:00
         - Update to use MRO::Compat

Modified: trunk/Catalyst-Plugin-PageCache/Makefile.PL
===================================================================
--- trunk/Catalyst-Plugin-PageCache/Makefile.PL	2010-11-01 15:23:57 UTC (rev 13674)
+++ trunk/Catalyst-Plugin-PageCache/Makefile.PL	2010-11-01 18:43:50 UTC (rev 13675)
@@ -6,6 +6,7 @@
 requires 'Catalyst::Runtime' => '0';
 requires 'Test::More';
 requires 'MRO::Compat' => '0.10';
+requires 'Digest::SHA1' => '0';
 
 auto_install;
 resources repository => 'http://dev.catalyst.perl.org/repos/Catalyst/trunk/Catalyst-Plugin-PageCache/';

Modified: trunk/Catalyst-Plugin-PageCache/lib/Catalyst/Plugin/PageCache.pm
===================================================================
--- trunk/Catalyst-Plugin-PageCache/lib/Catalyst/Plugin/PageCache.pm	2010-11-01 15:23:57 UTC (rev 13674)
+++ trunk/Catalyst-Plugin-PageCache/lib/Catalyst/Plugin/PageCache.pm	2010-11-01 18:43:50 UTC (rev 13675)
@@ -3,6 +3,7 @@
 use strict;
 use base qw/Class::Accessor::Fast/;
 use MRO::Compat;
+use Digest::SHA1 ();
 
 our $VERSION = '0.21';
 
@@ -319,6 +320,7 @@
 
     my $key = $c->_get_page_cache_key;
     my $config_PageCache = $c->config->{'Plugin::PageCache'};
+    my $now = time();
 
     my $headers = $c->res->headers;
 
@@ -422,11 +424,12 @@
 sub _get_page_cache_key {
     my $c = shift;
     
-    # We can't rely on the params after the user's code has run, so
-    # use the key created during the initial dispatch phase
+    # We can't rely on the params after the user's code has run,
+    # so we cache the key created during the initial dispatch phase
+    # and reuse it at finalize time.
     return $c->_page_cache_key if ( $c->_page_cache_key );
 
-    # override key if required
+    # override key if required, else use uri path
     my $keymaker = $c->config->{'Plugin::PageCache'}->{key_maker};
     my $key = $keymaker ? $keymaker->($c) : "/" . $c->req->path;
     
@@ -435,22 +438,31 @@
         $key = ':' . $c->language . ':' . $key;
     }
 
-    if ( scalar $c->req->param ) {
-        my @params;
-        foreach my $arg ( sort keys %{ $c->req->params } ) {
-            if ( ref $c->req->params->{$arg} ) {
-                my $list = $c->req->params->{$arg};
-                push @params, map { "$arg=" . $_  } sort @{$list};
-            }
-            else {
-                push @params, "$arg=" . $c->req->params->{$arg};
-            }
-        }
-        $key .= '?' . join( '&', @params );
+    # some caches have limits on the max key length (eg for memcached it's 250
+    # minus the namespace length) so if the key is a non-trvial length then
+    # replace the tail with a sha1. (We only replace the tail because it's
+    # useful to be able to see the leading portion of the path in the debug logs)
+    if (length($key) > 100) {
+        substr($key, 100) = Digest::SHA1::sha1_hex($key); # 40 bytes
     }
+    # Check for spaces as it's cheap insurance, just in case, for memcached
+    $key =~ s/\s/~/g;
+
+    # we always sha1 the parameters/query as they're typically long
+    # and it also avoids issues like spaces in keys for memcached
+    my $params_key;
+    my $parameters = $c->req->parameters;
+    if (%$parameters) {
+        local $Storable::canonical = 1;
+        $params_key = Storable::nfreeze($parameters);
+    }
     elsif ( my $query = $c->req->uri->query ) {
-        $key .= '?' . $query;
+        $params_key = $query;
     }
+    # use sha1 to avoid problems with over-long params or params
+    # containing values that can't be used as a key (eg spaces for memcached)
+    $key .= '?' . Digest::SHA1::sha1_hex($params_key) # 40 bytes
+        if $params_key;
 
     $c->_page_cache_key( $key );
 

Modified: trunk/Catalyst-Plugin-PageCache/t/08params.t
===================================================================
--- trunk/Catalyst-Plugin-PageCache/t/08params.t	2010-11-01 15:23:57 UTC (rev 13674)
+++ trunk/Catalyst-Plugin-PageCache/t/08params.t	2010-11-01 18:43:50 UTC (rev 13675)
@@ -30,12 +30,12 @@
 ok( $res = request('http://localhost/cache/count?c=3&b=2&a=1'), 'request ok' );
 is( $res->content, 1, 'count is still 1 from cache' );
 
-# test duplicate params
+# test multi-value params
 ok( $res = request('http://localhost/cache/count?a=1&a=2&a=3&b=4&c=5'), 'request ok' );
 is( $res->content, 2, 'count is 2' );
-
-# page will be served from cache even though params are different order
+# page NOT served from cache because multi-values for 'a' are in a different order
+# and we treat that as significant
 ok( $res = request('http://localhost/cache/count?b=4&c=5&a=2&a=3&a=1'), 'request ok' );
-is( $res->content, 2, 'count is still 2 from cache' );
+is( $res->content, 3, 'order of repeated param is significant' );
 
 




More information about the Catalyst-commits mailing list