Skip Menu |

This queue is for tickets about the Catalyst-Plugin-PageCache CPAN distribution.

Report information
The Basics
Id: 38524
Status: resolved
Priority: 0/
Queue: Catalyst-Plugin-PageCache

People
Owner: Nobody in particular
Requestors: m.e [...] acm.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: (no value)
Fixed in: (no value)



Subject: [PATCH] White labelling
Patch to allow override to page key to allow different pages to be served based on site name, user name etc.
Subject: 14keymaker.t
#!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 => 8 ); } # 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}->{key_maker} = sub { my ($c) = @_; return $c->req->base . q{/} . $c->req->path; }; # cache a page ok( my $res = request('http://host1/cache/count'), 'request ok' ); is( $res->content, 1, 'count is 1' ); # page will be served from cache ok( $res = request('http://host1/cache/count'), 'request ok' ); is( $res->content, 1, 'count is still 1 from cache' ); # page will not be served from cache ok( $res = request('http://host2/cache/count'), 'request ok' ); is( $res->content, 2, 'count is 2 from cache' ); # page will be served from cache ok( $res = request('http://host2/cache/count'), 'request ok' ); is( $res->content, 2, 'count is still 2 from cache' );
Subject: patch.txt
Index: PageCache.pm =================================================================== @@ -311,13 +313,15 @@ 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 return $c->_page_cache_key if ( $c->_page_cache_key ); - my $key = "/" . $c->req->path; - + # override key if required + my $keymaker = $c->config->{page_cache}->{key_maker}; + my $key = $keymaker ? $keymaker->($c) : "/" . $c->req->path; + # prepend language if I18N present. if ( $c->can('language') ) { $key = ':' . $c->language . ':' . $key; @@ -479,6 +483,17 @@ Note that this is called BEFORE auto_check_user, so you have more flexibility to determine what to do for not logged in users. +To override the generation of page keys: + +__PACKAGE__->config( + page_cache => { + key_maker => sub { + my ($c) = @_; + return $c->req->base . '/' . $c->req->path; + } + } +); + =head1 METHODS =head2 cache_page
Subject: Re: [rt.cpan.org #38524] [PATCH] White labelling
Date: Mon, 18 Aug 2008 11:00:38 +0100
To: Martin via RT <bug-Catalyst-Plugin-PageCache [...] rt.cpan.org>
From: Matt S Trout <mst [...] shadowcat.co.uk>
On Sat, Aug 16, 2008 at 11:13:40AM -0400, Martin via RT wrote: Show quoted text
> Sat Aug 16 11:13:36 2008: Request 38524 was acted upon. > Transaction: Ticket created by m.e > Queue: Catalyst-Plugin-PageCache > Subject: [PATCH] White labelling > Broken in: (no value) > Severity: Normal > Owner: Nobody > Requestors: m.e@acm.org > Status: new > Ticket <URL: http://rt.cpan.org/Ticket/Display.html?id=38524 > > > > Patch to allow override to page key to allow different pages to be > served based on site name, user name etc.
wrong config key still. -- Matt S Trout Need help with your Catalyst or DBIx::Class project? Technical Director http://www.shadowcat.co.uk/catalyst/ Shadowcat Systems Ltd. Want a managed development or deployment platform? http://chainsawblues.vox.com/ http://www.shadowcat.co.uk/servers/
Subject: ...with Plugin::PageCache key
From: m.e [...] acm.org
i have added a new version of the patch and the test file. This uses the new Plugin::PageCache key.
#!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 => 8 ); } # 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 # cannot call TestApp->config() because TestApp has already called setup TestApp->config->{'Plugin::PageCache'}->{key_maker} = sub { my ($c) = @_; return $c->req->base . q{/} . $c->req->path; }; # cache a page ok( my $res = request('http://host1/cache/count'), 'request ok' ); is( $res->content, 1, 'count is 1' ); # page will be served from cache ok( $res = request('http://host1/cache/count'), 'request ok' ); is( $res->content, 1, 'count is still 1 from cache' ); # page will not be served from cache ok( $res = request('http://host2/cache/count'), 'request ok' ); is( $res->content, 2, 'count is 2 from cache' ); # page will be served from cache ok( $res = request('http://host2/cache/count'), 'request ok' ); is( $res->content, 2, 'count is still 2 from cache' );
Index: PageCache.pm =================================================================== --- PageCache.pm (revision 756) +++ PageCache.pm (working copy) @@ -24,7 +24,7 @@ if ( ref($args[0]) eq 'HASH' || @args > 1 ) { my $options = ref( $args[0] ) ? shift : { @args }; - $options->{cache_seconds} = $c->config->{page_cache}->{expires} + $options->{cache_seconds} = $c->config->{'Plugin::PageCache'}->{expires} unless exists $options->{cache_seconds}; $c->_cache_page( $options ); @@ -37,9 +37,8 @@ $expires = $expires->epoch - time if ref($expires) && $expires->isa('DateTime'); + $expires ||= $c->config->{'Plugin::PageCache'}->{expires}; - $expires ||= $c->config->{page_cache}->{expires}; - # mark the page for caching during finalize if ( $expires > 0 ) { $c->_cache_page( { cache_seconds => $expires } ); @@ -61,11 +60,12 @@ delete $index->{$key}; $removed++; $c->log->debug( "Removed $key from page cache" ) - if ( $c->config->{page_cache}->{debug} ); + if ($c->config->{'Plugin::PageCache'}->{debug}); } } $c->cache->set( "_page_cache_index", $index, - $c->config->{page_cache}->{no_expire} ) if ( $removed ); + $c->config->{'Plugin::PageCache'}->{no_expire}) + if ($removed); } sub dispatch { @@ -74,15 +74,16 @@ # 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; + my $hook = + $c->config->{'Plugin::PageCache'}->{cache_hook} + ? $c->can($c->config->{'Plugin::PageCache'}->{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') && - $c->user_exists - ); + return $c->NEXT::dispatch(@_) + if ( $c->config->{'Plugin::PageCache'}->{auto_check_user} + && $c->can('user_exists') + && $c->user_exists); # check the page cache for a cached copy of this page return $c->NEXT::dispatch(@_) @@ -95,30 +96,28 @@ if ( $data->{expire_time} and $data->{expire_time} <= time ) { $c->log->debug( "Expiring $key from page cache" ) - if ( $c->config->{page_cache}->{debug} ); + if ($c->config->{'Plugin::PageCache'}->{debug}); $c->cache->remove( $key ); my $index = $c->cache->get( "_page_cache_index" ) || {}; delete $index->{$key}; $c->cache->set( "_page_cache_index", $index, - $c->config->{page_cache}->{no_expire} ); + $c->config->{'Plugin::PageCache'}->{no_expire}); return $c->NEXT::dispatch(@_); } - $c->log->debug( "Serving $key from page cache, expires in " . - ( $data->{expire_time} - time ) . " seconds" ) - if ( $c->config->{page_cache}->{debug} ); + $c->log->debug("Serving $key from page cache, expires in " + . ($data->{expire_time} - time) + . " seconds") + if ($c->config->{'Plugin::PageCache'}->{debug}); $c->_page_cache_used( 1 ); - # Check If-Modified-Since headers return 1 if $c->_page_cache_not_modified( $data ); - - # Serve cached page $c->res->body( $data->{body} ); @@ -126,11 +125,9 @@ $c->res->content_type( join '; ', @{$data->{content_type}} ) if $data->{content_type}; - $c->res->content_encoding( $data->{content_encoding} ) if $data->{content_encoding}; - $c->_set_page_cache_headers( $data ); $c->res->header('X-PageCache', 'Catalyst'); @@ -157,15 +154,13 @@ return; } - # Sets cache headers for the page if set_http_headers is true. sub _set_page_cache_headers { my ( $c, $data ) = @_; - return unless $c->config->{page_cache}->{set_http_headers}; + return unless $c->config->{'Plugin::PageCache'}->{set_http_headers}; - if ( exists $data->{expires} ) { # page cache but not client cache @@ -175,15 +170,16 @@ return; } - $c->res->headers->header( 'Cache-Control' => - "max-age=" . $data->{expires} ); + $c->res->headers->header( + 'Cache-Control' => "max-age=" . $data->{expires}); $c->res->headers->expires( time + $data->{expires} ); - } else { + } + else { - $c->res->headers->header( 'Cache-Control' => - "max-age=" . ( $data->{expire_time} - time ) ); + $c->res->headers->header( + 'Cache-Control' => "max-age=" . ($data->{expire_time} - time)); $c->res->headers->expires( $data->{expire_time} ); } @@ -198,33 +194,37 @@ # 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; + my $hook = + $c->config->{'Plugin::PageCache'}->{cache_hook} + ? $c->can($c->config->{'Plugin::PageCache'}->{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') && - $c->user_exists - ); + return $c->NEXT::finalize(@_) + if ( $c->config->{'Plugin::PageCache'}->{auto_check_user} + && $c->can('user_exists') + && $c->user_exists); return $c->NEXT::finalize(@_) if ( scalar @{ $c->error } ); # if we already served the current request from cache, we can skip the # rest of this method return $c->NEXT::finalize(@_) if ( $c->_page_cache_used ); - if ( !$c->_cache_page && scalar @{ $c->config->{page_cache}->{auto_cache} } ) { + if (!$c->_cache_page + && scalar @{ $c->config->{'Plugin::PageCache'}->{auto_cache} }) + { + # is this page part of the auto_cache list? my $path = "/" . $c->req->path; # For performance, this should be moved to setup, and generate a hash. AUTO_CACHE: - foreach my $auto ( @{ $c->config->{page_cache}->{auto_cache} } ) { + foreach my $auto (@{ $c->config->{'Plugin::PageCache'}->{auto_cache} }) + { next if $auto =~ m/^\d$/; if ( $path =~ /^$auto$/ ) { $c->log->debug( "Auto-caching page $path" ) - if ( $c->config->{page_cache}->{debug} ); + if ($c->config->{'Plugin::PageCache'}->{debug}); $c->cache_page; last AUTO_CACHE; } @@ -236,17 +236,19 @@ my $now = time; + $c->log->debug( + "Caching page $key for $options->{cache_seconds} seconds") + if ($c->config->{'Plugin::PageCache'}->{debug}); - $c->log->debug( "Caching page $key for $options->{cache_seconds} seconds" ) - if ( $c->config->{page_cache}->{debug} ); - # Cache some additional metadata along with the content # Some caches don't support expirations, so we do it manually my $data = { body => $c->res->body || undef, content_type => [ $c->res->content_type ] || undef, content_encoding => $c->res->content_encoding || undef, - create_time => $options->{last_modified} || $c->res->headers->last_modified || $now, + create_time => $options->{last_modified} + || $c->res->headers->last_modified + || $now, expire_time => $now + $options->{cache_seconds}, }; @@ -256,7 +258,6 @@ $c->_set_page_cache_headers( $data ); # don't forget the first time - # Keep an index cache of all pages that have been cached, for use # with clear_cached_page @@ -265,7 +266,7 @@ # Save date in cache $c->cache->set( "_page_cache_index", $index, - $c->config->{page_cache}->{no_expire} ); + $c->config->{'Plugin::PageCache'}->{no_expire}); # Check for If-Modified-Since $c->_page_cache_not_modified( $data ); @@ -279,10 +280,14 @@ $c->NEXT::setup(@_); - $c->config->{page_cache}->{auto_cache} ||= []; - $c->config->{page_cache}->{expires} ||= 60 * 5; - $c->config->{page_cache}->{set_http_headers} ||= 0; - $c->config->{page_cache}->{debug} ||= $c->debug; + # allow code using old config key to work + if ($c->config->{page_cache} and !$c->config->{'Plugin::PageCache'}) { + $c->config->{'Plugin::PageCache'} = $c->config->{page_cache}; + } + $c->config->{'Plugin::PageCache'}->{auto_cache} ||= []; + $c->config->{'Plugin::PageCache'}->{expires} ||= 60 * 5; + $c->config->{'Plugin::PageCache'}->{set_http_headers} ||= 0; + $c->config->{'Plugin::PageCache'}->{debug} ||= $c->debug; # detect the cache plugin being used and set appropriate # never-expires syntax @@ -295,13 +300,15 @@ # Older Cache plugins if ( $c->cache->isa('Cache::FileCache') ) { - $c->config->{page_cache}->{no_expire} = "never"; + $c->config->{'Plugin::PageCache'}->{no_expire} = "never"; } - elsif ( $c->cache->isa('Cache::Memcached') || - $c->cache->isa('Cache::FastMmap') ) { + elsif ($c->cache->isa('Cache::Memcached') + || $c->cache->isa('Cache::FastMmap')) + { + # Memcached defaults to 'never' when not given an expiration # In FastMmap, it's not possible to set an expiration - $c->config->{page_cache}->{no_expire} = undef; + $c->config->{'Plugin::PageCache'}->{no_expire} = undef; } } else { @@ -316,7 +323,9 @@ # use the key created during the initial dispatch phase return $c->_page_cache_key if ( $c->_page_cache_key ); - my $key = "/" . $c->req->path; + # override key if required + my $keymaker = $c->config->{'Plugin::PageCache'}->{key_maker}; + my $key = $keymaker ? $keymaker->($c) : "/" . $c->req->path; # prepend language if I18N present. if ( $c->can('language') ) { @@ -357,7 +366,8 @@ use Catalyst; MyApp->setup( qw/Cache::FileCache PageCache/ ); - MyApp->config->{page_cache} = { + __PACKAGE__->config( + 'Plugin::PageCache' => { expires => 300, set_http_headers => 1, auto_cache => [ @@ -369,7 +379,7 @@ # 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 ) = @_; @@ -479,6 +489,17 @@ Note that this is called BEFORE auto_check_user, so you have more flexibility to determine what to do for not logged in users. +To override the generation of page keys: + +__PACKAGE__->config( + 'Plugin::PageCache' => { + key_maker => sub { + my ($c) = @_; + return $c->req->base . '/' . $c->req->path; + } + } +); + =head1 METHODS =head2 cache_page
On Fri Aug 22 02:48:35 2008, m.e wrote: Show quoted text
> i have added a new version of the patch and the test file. This uses the > new Plugin::PageCache key.
Thanks for the patch. Unfortunately it looks like it breaks a lot of the other tests: Failed Test Stat Wstat Total Fail Failed List of Failed ------------------------------------------------------------------------------- t/05expires.t 1 256 6 1 16.67% 6 t/06auto_cache.t 3 768 8 3 37.50% 4 6 8 t/07set_http_headers.t 3 768 7 3 42.86% 5-7 t/09datetime.t 3 768 7 3 42.86% 5-7 t/10options.t 3 768 7 3 42.86% 5-7 t/11nocache.t 2 512 7 2 28.57% 5-6 t/13cachehook.t 5 1280 16 5 31.25% 5 11 13-15 2 tests skipped. Failed 7/15 test scripts, 53.33% okay. 20/121 subtests failed, 83.47% okay.
Subject: [PATCH] ...patch existing tests
From: m.e [...] acm.org
Please also apply the attached patch to the test files. The problem is that the tests are modifying the config hash after setup has been run.
Index: t/05expires.t =================================================================== --- t/05expires.t (revision 768) +++ t/05expires.t (working copy) @@ -21,7 +21,7 @@ use Catalyst::Test 'TestApp'; # add config option -TestApp->config->{page_cache}->{expires} = 2; +TestApp->config->{'Plugin::PageCache'}->{expires} = 2; # cache a page ok( my $res = request('http://localhost/cache/count'), 'request ok' ); Index: t/06auto_cache.t =================================================================== --- t/06auto_cache.t (revision 768) +++ t/06auto_cache.t (working copy) @@ -21,7 +21,7 @@ use Catalyst::Test 'TestApp'; # add config option -TestApp->config->{page_cache}->{auto_cache} = [ +TestApp->config->{'Plugin::PageCache'}->{auto_cache} = [ '/cache/auto_count', '/cache/another.+', ]; Index: t/07set_http_headers.t =================================================================== --- t/07set_http_headers.t (revision 768) +++ t/07set_http_headers.t (working copy) @@ -21,7 +21,7 @@ use Catalyst::Test 'TestApp'; # add config option -TestApp->config->{page_cache}->{set_http_headers} = 1; +TestApp->config->{'Plugin::PageCache'}->{set_http_headers} = 1; # cache a page my $cache_time = time; Index: t/09datetime.t =================================================================== --- t/09datetime.t (revision 768) +++ t/09datetime.t (working copy) @@ -30,7 +30,7 @@ use Catalyst::Test 'TestApp'; # add config option -TestApp->config->{page_cache}->{set_http_headers} = 1; +TestApp->config->{'Plugin::PageCache'}->{set_http_headers} = 1; # cache a page my $cache_time = time; Index: t/10options.t =================================================================== --- t/10options.t (revision 768) +++ t/10options.t (working copy) @@ -23,7 +23,7 @@ use Catalyst::Test 'TestApp'; # add config option -TestApp->config->{page_cache}->{set_http_headers} = 1; +TestApp->config->{'Plugin::PageCache'}->{set_http_headers} = 1; # cache a page my $cache_time = time; Index: t/11nocache.t =================================================================== --- t/11nocache.t (revision 768) +++ t/11nocache.t (working copy) @@ -23,7 +23,7 @@ use Catalyst::Test 'TestApp'; # add config option -TestApp->config->{page_cache}->{set_http_headers} = 1; +TestApp->config->{'Plugin::PageCache'}->{set_http_headers} = 1; # cache a page my $cache_time = time; Index: t/13cachehook.t =================================================================== --- t/13cachehook.t (revision 768) +++ t/13cachehook.t (working copy) @@ -24,8 +24,8 @@ use Catalyst::Test 'TestApp'; # add config option -TestApp->config->{page_cache}->{set_http_headers} = 1; -TestApp->config->{page_cache}->{cache_hook} = 'use_pagecache'; +TestApp->config->{'Plugin::PageCache'}->{set_http_headers} = 1; +TestApp->config->{'Plugin::PageCache'}->{cache_hook} = 'use_pagecache'; local *TestApp::use_pagecache = sub { 0 }; cmp_ok( TestApp->use_pagecache(), '==', '0' );
Applied in 0.19.