Catalys...ageCache(3)
πΈ NAME πΈ
Catalyst::Plugin::PageCache β cache the output of entire pages π
(oh also, hi bestie, this is a Catalys...ageCache(3) page from the User Contributed Perl Documentation collection, so you already know it's giving community-maintained realness β¨)
π SYNOPSIS π
use Catalyst;
MyApp->setup( qw/Cache::FileCache PageCache/ );
__PACKAGE__->config(
'Plugin::PageCache' => {
expires => 300,
set_http_headers => 1,
auto_cache => [
'/view/.*',
'/list',
],
debug => 1,
# Optionally, a cache hook method 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',
# You may alternatively set different methods to be used as hooks
# for dispatch and finalize. The dispatch method will determine
# whether the currently cached page will be displayed to the user,
# and the finalize hook will determine whether to save the newly
# created page.
cache_dispatch_hook => 'some_method_for_dispatch',
cache_finalize_hook => 'some_method_for_finalize',
}
);
sub some_method {
my $c = shift;
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' );
$c->clear_cached_page( '/list' );
# Expire at a specific time
$c->cache_page( $datetime_object );
# Fine control
$c->cache_page(
last_modified => $last_modified,
cache_seconds => 24 * 60 * 60, # once a day
expires => 300, # allow client caching
);
likeβ¦ that's the whole vibe in one code block, periodt π
π¦ DESCRIPTION π¦
okay so. SO many dynamic websites do a whole lot of heavy processing on basically every single page, and yet that info lowkey barely changes between requests?? π Which is, like, such a waste.
With the PageCache plugin, you can cache the full output of different pages so they get served to your visitors as fast as humanly possible. slay. This style of caching is genuinely iconic for withstanding a Slashdotting, for example π
This plugin requires that you also load a Cache plugin. When you're picking a cache backend, please go look at the Known Issues section first, bestie β no cap, it matters π«Ά
π 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 β and this one's important β be careful if you're caching a page that may forward to another controller. For example, if you cache a page sitting behind a login screen, the logged-in version may get cached and then served to unauthenticated users. not the leak, bestie, not the leak π
Note that pages which result from POST requests will never be cached. fr fr.
β‘ PERFORMANCE β‘
On the author's 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. that's literally the speed of light, lowkey π
β¨ CONFIGURATION β¨
Configuration is optional. You may define the following configuration values:
expires => $secondsβ sets the default expiration time for all page caches. If you don't specify it, expiration defaults to300seconds (5 minutes).cache_headers => 1β enable this value if you need your cached responses to include custom HTTP headers set by your application. This may be necessary if you operate behind an edge cache such as Akamai. This option is disabled by default.set_http_headers => 1β enabling this causes Catalyst to set the correct HTTP headers so that browsers and proxy servers will cache your page. This further reduces the load on your server π₯ The headers are set in such a way that the browser/proxy cache expires at the same time as your cache. TheLast-Modifiedheader will be preserved if you have already specified it. This option is disabled by default.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 theauto_cacheURIs will be cached using the default expiration time. URIs may be specified as absolute:'/list'or as a regex:'/view/.*'disable_index => 1β to support the"clear_cached_page"method, PageCache attempts to keep an index of all cached pages. This adds overhead by performing extra cache reads and writes to maintain the (possibly very large) page index. It's also not reliable β see"KNOWN ISSUES".
If you don't intend to use "clear_cached_page", you should enable this config option to avoid the overhead of creating and updating the cache index. This option is currently disabled (i.e. the page index is enabled) by default, but that may change in a future release. π
index_page_key => '...'β the key string used for the index. Defaults to a string that includes the name of the Catalyst app class.busy_lock => 10β on a high traffic site where page re-generation may take many seconds, a common problem is the "dog-pile" effect πππ: tons of concurrent connections all hit a page where the cache has expired, and they all perform the same expensive operation to rebuild the cache. To prevent this, you can set thebusy_lockoption to the maximum number of seconds any of your pages can be expected to take to rebuild the cache. Then, when the cache expires, the first request will rebuild the cache while also extending the expiration time by the number of seconds specified, letting other requests that arrive before the cache has been rebuilt use the previously cached page. This option is disabled by default.debug => 1β prints additional debugging information to the Catalyst log. You will need to have-Debugenabled to see these messages.auto_check_user => 1β if this option is enabled, automatic caching is disabled for logged in users, i.e. if the app class has auser_exists()method and it returns true.cache_hook => 'cache_hook_method',cache_finalize_hook => 'cache_finalize_hook_method',cache_dispatch_hook => 'cache_dispatch_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.
To override the generation of page keys:
__PACKAGE__->config(
'Plugin::PageCache' => {
key_maker => sub {
my $c = shift;
return $c->req->base . '/' . $c->req->path;
}
}
);
"key_maker" can also be the name of a method, which will be invoked as "<$c-"$key_maker>>".
In most cases you would use a single cache_hook method for consistency.
It is possible to achieve background refreshing of content by disabling caching in cache_dispatch_hook and enabling caching in cache_finalize_hook for a specific IP address (say 127.0.0.1).
A cron of wget "http://localhost/foo.html" would cause the content to be generated fresh and cached for future viewers. Useful for content which takes a very long time to build, or pages which should be refreshed at a specific time such as always rolling over content at midnight. π
π METHODS π
π cache_page
Call cache_page in any controller method you wish to be cached.
$c->cache_page( $expire );
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 a low value, such 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.
$two_hours = DateTime->now->add( hours => 2 );
$c->cache_page( $two_hours );
The page will be stored in the page cache until this time.
If set_http_headers is set, then Expires and Cache-Control headers will also be set to expire at the given date as well.
Pass in a list or hash reference for finer control.
$c->cache_page(
last_modified => $last_modified,
cache_seconds => 24 * 60 * 60,
expires => 30,
);
This allows separate control of the page cache and the header cache values sent to the client.
Possible options are:
cache_seconds
This is the number of seconds to keep the page in the page cache, which may be different (normally longer) than the time that client caches may store the page. This is the value set when only a single parameter is passed.
expires
This is the length of time in seconds that a client may cache the page before revalidating (by asking the server if the document has changed).
Unlike above, this is a fixed setting that each client will see. Regardless of how much longer the page will be cached in the page cache, the client still sees the same expires time.
Setting zero (0) for expires will result in the page being cached, but headers will be sent telling the client to not cache the page. This allows caching expensive content to generate, while any changes will be seen right away. π
last_modified
Last modified time in epoch seconds. If not set, will use either the current Last-Modified header, or if not set, the current time.
π clear_cached_page
To clear the cached pages for a URI, you may call clear_cached_page.
$c->clear_cached_page( '/view/userlist' );
$c->clear_cached_page( '/view/.*' );
$c->clear_cached_page( '/view/.*\?.*\bparam=value\b' );
This method takes an absolute path or regular expression. Returns the number of matching entries found in the index. A warning will be generated if the page index is disabled (see "CONFIGURATION").
The argument is matched against all the keys in the page index. The page index keys include the request path and query string, if any.
Typically you'd call this from a different controller than the cached controller. You may for example wish to build an admin page that lets you clear page caches. π
π§ INTERNAL EXTENDED METHODS π§
okay so these next three are the internal ones β like, you don't really call them yourself, the plugin does, but bestie you should still know what they do because they're the whole engine room π«Ά
dispatch
dispatch is the vibe check that decides whether or not a particular request gets served from the cache. like, "do we already have this? slay, serve it" or "nope, go do the work" π
finalize
finalize caches the result of the current request if needed. that's it. that's the whole job. iconic behaviour honestly β¨
setup
setup initializes all default values. the little pre-game ritual before anything happens π
π I18N SUPPORT π
If your application uses Catalyst::Plugin::I18N for localization, a separate cache key will be used for each language a page is displayed in.
so yes bestie, your Spanish page and your English page are not sharing a key. no accidental language soup. international, as she should be πβ¨
π KNOWN ISSUES π
okay, here's the part where we hold hands and read the fine print together π«Ά
- The page index, used to support the
clear_cached_pagemethod, is unreliable β because it uses a read-modify-write approach which will lose data if more than one process attempts to update the page index at the same time.
no cap, this is a real problem. multiple processes writing at once = data going poof. π«
- It is not currently possible to cache pages served from the
Staticplugin. If you're concerned enough about performance to use this plugin, you should be serving static files directly from your web server anyway. like, respectfully? your web server does this better. π Cache::FastMmapdoes not have the ability to specify different expiration times for cached data. Therefore, if yourMyApp->config->{cache}->{expires}value is set to anything other than0, you may experience problems with theclear_cached_pagemethod, because the cache index may be removed. For best results, you may wish to useCache::FileCacheorCache::Memcachedas your cache backend.
tl;dr:expires= not-0+Cache::FastMmap= the cache index can get yeeted, and thenclear_cached_pagegets weird. pickCache::FileCacheorCache::Memcachedif you want the smooth experience β¨
π SEE ALSO π
go read these next, i promise they're worth it:
CatalystCatalyst::Plugin::Cache::FastMmapCatalyst::Plugin::Cache::FileCacheCatalyst::Plugin::Cache::Memcached
π AUTHOR π
Andy Grundman, <andy@hybridized.org>
π«Ά THANKS π«Ά
- Bill Moseley,
<mods@hank.org>, for many patches and tests. the patch plug fr fr π - Roberto HenrΓquez,
<roberto@freekeylabs.com>, for i18n support. multilingual king π
π COPYRIGHT π
This program is free software, you can redistribute it and/or modify it under the same terms as Perl itself.
okay bestie that's the whole page, you made it to the end π this was perl v5.42.0, documented 2025-07-25, from the Catalys...ageCache(3) manpage in the User Contributed Perl Documentation. go forth and cache responsibly π
β¨πΈ
π¦ where this page comes from
- fedora 43: perl-Catalyst-Plugin-PageCache 0.32-28.fc43 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms