File Coverage

blib/lib/Dancer2/Plugin/Cache/CHI.pm
Criterion Covered Total %
statement 49 52 94.2
branch 11 14 78.5
condition 4 7 57.1
subroutine 13 14 92.8
pod n/a
total 77 87 88.5


line stmt bran cond sub pod time code
1             package Dancer2::Plugin::Cache::CHI;
2             our $AUTHORITY = 'cpan:YANICK';
3             # ABSTRACT: Dancer plugin to cache response content (and anything else)
4             $Dancer2::Plugin::Cache::CHI::VERSION = '1.7.1';
5 6     6   2876278 use strict;
  6         16  
  6         176  
6 6     6   32 use warnings;
  6         11  
  6         158  
7 6     6   43 use Carp;
  6         9  
  6         382  
8 6     6   5553 use CHI;
  6         314824  
  6         190  
9              
10 6     6   4662 use Dancer2::Plugin;
  6         14924  
  6         41  
11              
12             register_hook 'before_create_cache';
13              
14              
15             my %cache;
16             my $cache_page; # actually hold the ref to the args
17             my $cache_page_key_generator = sub {
18             return $_[0]->app->request->path;
19             };
20              
21             on_plugin_import {
22             my $dsl = shift;
23              
24             $dsl->app->add_hook(
25             Dancer2::Core::Hook->new(
26             name => 'after',
27             code => sub {
28             return unless $cache_page;
29              
30             my $resp = shift;
31             cache($dsl)->set( $cache_page_key_generator->($dsl),
32             {
33             status => $resp->status,
34             headers => $resp->headers_to_array,
35             content => $resp->content
36             },
37             @$cache_page,
38             );
39              
40             $cache_page = undef;
41             }
42             ));
43             };
44              
45             register cache => sub {
46 60     60   96979 my $dsl = shift;
47 60   50     658 return $cache{$_[0]//''} ||= _create_cache( $dsl, @_ );
      66        
48             };
49              
50             my $honor_no_cache = 0;
51              
52             sub _create_cache {
53 5     5   12 my $dsl = shift;
54 5         13 my $namespace = shift;
55 5   50     49 my $args = shift || {};
56              
57 5         109 $dsl->execute_hook( 'plugin.cache_chi.before_create_cache' );
58              
59             my %setting = %{
60 5 50       725 $dsl->app->config->{plugins}{'Cache::CHI'} || {}
  5         39  
61             };
62              
63 5 50       203 $setting{namespace} = $namespace if defined $namespace;
64              
65 5         32 while( my ( $k, $v ) = each %$args ) {
66 0         0 $setting{$k} = $v;
67             }
68              
69             $honor_no_cache = delete $setting{honor_no_cache}
70 5 100       37 if exists $setting{honor_no_cache};
71              
72 5         61 return CHI->new(%setting);
73             }
74              
75              
76              
77             register check_page_cache => sub {
78 4     4   5488 my $dsl = shift;
79              
80             my $hook = sub {
81 33     33   2443267 my $context = shift;
82              
83             # Instead halt() now we use a more correct method - setting of a
84             # response to Dancer2::Core::Response object for a more correct returning of
85             # some HTTP headers (X-Powered-By, Server)
86              
87 33 100       113 my $cached = cache($dsl)->get( $cache_page_key_generator->($dsl) )
88             or return;
89              
90 9 100       1427 if ( $honor_no_cache ) {
91              
92 5         17 my $req = $dsl->app->request;
93              
94 6     6   15565 no warnings 'uninitialized';
  6         12  
  6         2146  
95              
96             return if grep {
97             # eval is there to protect from a regression in Dancer 1.31
98             # where headers can be undef
99 5 100       10 eval { $req->header($_) eq 'no-cache' }
  10         779  
  10         36  
100             } qw/ Cache-Control Pragma /;
101             }
102              
103             $context->set_response(
104             Dancer2::Core::Response->new(
105             is_halted => 1,
106             ref $cached eq 'HASH'
107             ?
108             (
109             status => $cached->{status},
110             headers => $cached->{headers},
111             content => $cached->{content}
112             )
113 7 50       298 :
114             ( content => $cached )
115             )
116             );
117 4         31 };
118              
119 4         132 $dsl->app->add_hook( Dancer2::Core::Hook->new(
120             name => 'before',
121             code => $hook,
122             ));
123             };
124              
125              
126             register cache_page => sub {
127 13     13   11189 shift;
128              
129 13         32 my ( $content, @args ) = @_;
130              
131 13         30 $cache_page = \@args;
132              
133 13         45 return $content;
134             };
135              
136              
137              
138             register cache_page_key => sub {
139 0     0   0 shift;
140 0         0 return $cache_page_key_generator->();
141             };
142              
143              
144             register cache_page_key_generator => sub {
145 1     1   2040 shift;
146 1         5 $cache_page_key_generator = shift;
147             };
148              
149              
150             for my $method ( qw/ set get remove clear compute / ) {
151             register 'cache_'.$method => sub {
152 11     11   115202 my $dsl = shift;
153 11         27 return cache($dsl)->$method( @_ );
154             }
155             }
156              
157              
158             register_plugin for_versions => [1,2];
159              
160             1;
161              
162             __END__