File Coverage

blib/lib/Dancer/Plugin/Cache/CHI.pm
Criterion Covered Total %
statement 59 61 96.7
branch 10 12 83.3
condition 4 7 57.1
subroutine 20 21 95.2
pod 0 1 0.0
total 93 102 91.1


line stmt bran cond sub pod time code
1             package Dancer::Plugin::Cache::CHI;
2             our $AUTHORITY = 'cpan:YANICK';
3             # ABSTRACT: Dancer plugin to cache response content (and anything else)
4             $Dancer::Plugin::Cache::CHI::VERSION = '1.5.0';
5 5     5   1092472 use strict;
  5         41  
  5         117  
6 5     5   20 use warnings;
  5         8  
  5         108  
7 5     5   20 no warnings qw/ uninitialized /;
  5         8  
  5         223  
8              
9 5     5   26 use Dancer 1.32 ':syntax';
  5         97  
  5         23  
10              
11 5     5   1475 use Carp;
  5         9  
  5         245  
12 5     5   2420 use CHI;
  5         323551  
  5         161  
13              
14 5     5   1933 use Dancer::Plugin;
  5         6120  
  5         315  
15              
16 5     5   38 use Moo;
  5         10  
  5         31  
17              
18 5     5   2382 use Dancer::Factory::Hook;
  5         14  
  5         110  
19 5     5   25 use Dancer::Response;
  5         9  
  5         91  
20 5     5   21 use Dancer::SharedData;
  5         9  
  5         1422  
21              
22              
23             my %cache;
24             my $cache_page; # actually hold the ref to the args
25             my $cache_page_key_generator = sub {
26             return request()->{path_info};
27             };
28              
29             hook after => sub {
30             return unless $cache_page;
31              
32             my $resp = shift;
33             cache()->set( $cache_page_key_generator->(),
34             {
35             status => $resp->status,
36             headers => $resp->headers_to_array,
37             content => $resp->content
38             },
39             @$cache_page,
40             );
41              
42             $cache_page = undef;
43             };
44              
45             register cache => sub {
46 59   50 59   4679 return $cache{$_[0]//''} ||= _create_cache( @_ );
      66        
47             };
48              
49             my $honor_no_cache = 0;
50              
51             sub _create_cache {
52 4     4   9 my $namespace = shift;
53 4   50     17 my $args = shift || {};
54              
55 4         18 Dancer::Factory::Hook->execute_hooks( 'before_create_cache' );
56              
57 4         286 my %setting = %{ plugin_setting() };
  4         15  
58              
59 4 50       86 $setting{namespace} = $namespace if defined $namespace;
60              
61 4         19 while( my ( $k, $v ) = each %$args ) {
62 0         0 $setting{$k} = $v;
63             }
64              
65             $honor_no_cache = delete $setting{honor_no_cache}
66 4 100       19 if exists $setting{honor_no_cache};
67              
68 4         40 return CHI->new(%setting);
69             }
70              
71              
72              
73             sub should_skip_cache {
74 9 100   9 0 31 return unless $honor_no_cache;
75              
76 5         12 my $req = Dancer::SharedData->request;
77              
78 5     5   28 no warnings 'uninitialized';
  5         11  
  5         1597  
79              
80             return scalar grep {
81 5         17 $req->header($_) eq 'no-cache'
  10         176  
82             } qw/ Cache-Control Pragma /;
83             }
84              
85             register check_page_cache => sub {
86              
87             hook before => sub {
88             # Instead halt() now we use a more correct method - setting of a
89             # response to Dancer::Response object for a more correct returning of
90             # some HTTP headers (X-Powered-By, Server)
91              
92 32 100   32   2094872 my $cached = cache()->get( $cache_page_key_generator->() )
93             or return;
94              
95 9 100       1331 return if should_skip_cache();
96              
97             Dancer::SharedData->response(
98             Dancer::Response->new(
99             ref $cached eq 'HASH'
100             ?
101             (
102             status => $cached->{status},
103             headers => $cached->{headers},
104             content => $cached->{content}
105             )
106 7 50       130 :
107             ( content => $cached )
108             )
109             );
110 3     3   3151 };
111              
112             };
113              
114              
115             register cache_page => sub {
116 13     13   8989 my ( $content, @args ) = @_;
117              
118 13         28 $cache_page = \@args;
119              
120 13         37 return $content;
121             };
122              
123              
124              
125             register cache_page_key => sub {
126 0     0   0 return $cache_page_key_generator->();
127             };
128              
129              
130             register cache_page_key_generator => sub {
131 1     1   672 $cache_page_key_generator = shift;
132             };
133              
134              
135             for my $method ( qw/ set get remove clear compute / ) {
136             register 'cache_'.$method => sub {
137 11     11   9258 return cache()->$method( @_ );
138             }
139             }
140              
141             Dancer::Factory::Hook->instance->install_hooks(qw/ before_create_cache /);
142              
143              
144             register_plugin;
145              
146             __END__