File Coverage

blib/lib/Egg/Plugin/Cache/UA.pm
Criterion Covered Total %
statement 9 9 100.0
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 12 12 100.0


line stmt bran cond sub pod time code
1             package Egg::Plugin::Cache::UA;
2             #
3             # Masatoshi Mizuno E<lt>lusheE<64>cpan.orgE<gt>
4             #
5             # $Id: UA.pm 306 2008-03-07 10:55:58Z lushe $
6             #
7 2     2   612 use strict;
  2         4  
  2         80  
8 2     2   9 use warnings;
  2         4  
  2         74  
9 2     2   8 use base qw/ Egg::Plugin::LWP /;
  2         4  
  2         2228  
10              
11             our $VERSION = '1.01';
12              
13             sub _setup {
14             my($e)= @_;
15             my $conf= $e->config->{plugin_cache_ua} ||= {};
16             $conf->{content_type} ||= 'text/html';
17             $conf->{content_type_error} ||= 'text/html';
18             $conf->{cache_name} || die q{ I want setup 'cache_name'. };
19             $conf->{cache_expires} ||= undef;
20             my $allows= $conf->{allow_hosts} || die q{ I want setup 'allow_hosts' };
21             my $regex = join '|',
22             map{quotemeta}(ref($allows) eq 'ARRAY' ? @$allows: $allows);
23              
24             no warnings 'redefine';
25             *Egg::Plugin::Cache::UA::handler::referer_check= sub {
26             my($self)= @_;
27             my $referer= $self->e->request->referer || return 1;
28             $referer=~m{^https?\://(?:$regex)} ? 1: 0;
29             };
30              
31             $e->next::method;
32             }
33             sub cache_ua {
34             $_[0]->{cache_ua} ||= Egg::Plugin::Cache::UA::handler->new
35             ($_[0], $_[0]->config->{plugin_cache_ua});
36             }
37              
38             package Egg::Plugin::Cache::UA::handler;
39             use strict;
40             use warnings;
41             use Carp qw/ croak /;
42             use base qw/ Egg::Base /;
43              
44             *remove= \&delete;
45              
46             sub new {
47             my $self= shift->SUPER::new(@_);
48             $self->{cache}= {};
49             $self;
50             }
51             sub get {
52             my($self, $url, $option)= __get_args(@_);
53             $self->referer_check || return 0;
54             my $result= $self->cache($option->{cache_name})->get($url) || do {
55             my %attr;
56             my $method= uc $option->{request_method} || 'GET';
57             if (my $res= $self->e->ua->request( $method => $url )) {
58             if ($res->is_success) {
59             $attr{is_success}= 1;
60             if (my $status= $res->status_line) {
61             $attr{status}= $status if $status!~/^200/;
62             }
63             my @content_type= $res->header('content_type') || "";
64             $attr{content_type}= $content_type[0]
65             || $option->{content_type};
66             $attr{content}= $res->content || "";
67             } else {
68             $attr{status}= $res->status_line || '403 Forbidden';
69             $attr{error} = " Error in $url : ". $res->status_line;
70             }
71             } else {
72             $attr{status}= "408 Request Time-out";
73             $attr{error} = " $url doesn't return the response. ";
74             }
75             $attr{content_type} ||= $option->{content_type_error};
76             $attr{content} ||= "";
77             $self->cache->set($url, \%attr, $option->{cache_expires});
78             $attr{no_hit}= 1;
79             \%attr;
80             };
81             }
82             sub output {
83             my($self, $url, $option)= __get_args(@_);
84             my $cache= $self->get($url, $option) || {
85             no_hit => 1,
86             status => '500 Internal Server Error',
87             content_type => $option->{content_type_error},
88             error => ' referer is illegal.',
89             };
90             my $response= $self->e->response;
91             $response->headers->header('X-CACHE-UA'=> 'hit')
92             unless $cache->{no_hit};
93             $response->is_expires($option->{expires})
94             if $option->{expires};
95             $response->last_modified($option->{last_modified})
96             if $option->{last_modified};
97             $response->status($cache->{status}) if $cache->{status};
98             $response->content_type($cache->{content_type});
99             $cache->{content}= $cache->{error} if $cache->{error};
100             $response->body(\$cache->{content});
101             }
102             sub delete {
103             my $self= shift;
104             my($name, $url)= @_
105             ? (@_ > 1 ? @_: (undef, shift)): croak q{ I want url. };
106             $self->cache($name)->remove($url);
107             }
108             sub cache {
109             my $self= shift;
110             my $name= shift || $self->param('cache_name');
111             $self->{cache}{$name} ||= $self->e->model($name);
112             }
113             sub __get_args {
114             my $self = shift;
115             my $url = shift || croak q{ I want URL. };
116             my %option= (
117             %{$self->params},
118             %{ $_[1] ? {@_}: ($_[0] || {}) },
119             );
120             ($self, $url, \%option);
121             }
122              
123             1;
124              
125             __END__
126              
127             =head1 NAME
128              
129             Egg::Plugin::Cache::UA - The result of the WEB request is cached.
130              
131             =head1 SYNOPSIS
132              
133             package MyApp;
134             use Egg qw/Cache::UA/;
135             .......
136             .....
137              
138             package MyApp::Dispatch;
139             .........
140            
141             MyApp->dispatch_map(
142             ...........
143             cache=> {
144             google => sub {
145             my($e)= @_;
146             $e->cache_ua->output('http://xxx.googlesyndication.com/pagead/show_ads.js');
147             },
148             brainer=> sub {
149             my($e)= @_;
150             $e->cache_ua->output('http://xxx.brainer.jp/ad.js');
151             },
152             },
153             );
154              
155             =head1 DESCRIPTION
156              
157             This module caches and recycles the request result of L<Egg::Plugin::LWP>.
158              
159             Especially, I think that it is effective in the contents match system advertisement
160             etc. of the type that returns the JAVA script.
161             It becomes difficult to receive the influence of the response speed of advertisement
162             ASP server by the action of cashe.
163              
164             It is necessary to setup L<Egg::Model::Cache> to use it, and to set the label name
165             to acquire the model to 'cache_name' of the configuration.
166              
167             This module has succeeded to L<Egg::Plugin::LWP>.
168              
169             =head1 CONFIGURATION
170              
171             The configuration is set by 'plugin_cache_ua'.
172              
173             package MyApp;
174            
175             __PACKAGE__->startup(
176             plugin_cache_ua => {
177             cache_name => 'cache_model_name',
178             allow_hosts => [qw/ mydomain.name /],
179             content_type => 'text/html',
180             content_type_error => 'text/html',
181             cache_expires => 60* 60,
182             expires => '+1d',
183             last_modified => '+1d',
184             },
185             );
186              
187             =head3 allow_hosts
188              
189             The host name that permits the use of cashe is set with ARRAY.
190              
191             It is necessary to set this.
192              
193             allow_hosts => [qw/ www.domain.com domain.com domain.net /],
194              
195             When the regular expression is set, the access is not accepted because each value
196             is put on quotemeta.
197              
198             When it is not possible to acquire it, processing is continued disregarding this
199             setting though it checks with HTTP_REFERER of the environment variable because
200             the thing that cannot be acquired under the influences of the proxy and
201             the security software, etc. can break out, too.
202              
203             =head3 content_type
204              
205             Default of sent contents type.
206              
207             This setting is substitution when the contents type is not obtained because of the
208             WEB request.
209              
210             'text/html' is used if it unsets it.
211              
212             content_type=> 'text/javascript',
213              
214             =head3 content_type_error
215              
216             Contents type used when data is not obtained by some errors' occurring by WEB request.
217              
218             Default is 'text/html'.
219              
220             =head3 cache_name
221              
222             Model name of cashe used.
223              
224             The model name to acquire the cashe object set up with L<Egg::Model::Cache> is set.
225              
226             There is no default. Please set it.
227              
228             =head3 cache_expires
229              
230             It is a value passed to the third argument of 'set' method of cashe.
231              
232             This is a setting that assumes the use of L<Cache::Memcached>.
233              
234             cache_expires=> 60* 60, # It is effective for one hour.
235              
236             It is not necessary to set it usually.
237              
238             Validity term is done depending on the cashe model used.
239              
240             =head3 expires or last_modified
241              
242             The response header to press the cashe of the browser side is set.
243              
244             It specifies it by the form used by CGI module.
245              
246             expires => '+1d',
247             last_modified => '+1d',
248              
249             =head3 request_method
250              
251             It is request a method when WEB is requested.
252              
253             Default is 'GET'.
254              
255             I think that you should specify this when you are putting necessary in 'get'
256             method as undefined usually.
257              
258             $e->cache_ua->get( 'http://.....' => { request_method=> 'POST' } );
259              
260             =head1 NAME
261              
262             =head2 cache_ua
263              
264             The Egg::Plugin::Cache::UA::handler object is returned.
265              
266             my $cache_ua= $e->cache_ua;
267              
268             =head1 HADLER METHODS
269              
270             =head2 get ( [URL], [OPTION] )
271              
272             The request is sent to URL.
273              
274             The content is returned if becoming a hit to cashe.
275              
276             OPTION overwrites the default.
277              
278             The HASH reference returns to the return value without fail.
279              
280             my $res= $e->cache_ua->get('http://domainname/');
281            
282             if ($res->{is_success}) {
283             $e->stash->{request_content}= \$res->{content};
284             } else {
285             $e->finished($res->{status} || 500);
286             }
287              
288             The content of content is set in $e-E<gt>response-E<gt>body. When content is not
289             obtained by the error's occurring by the request, the content of error is set.
290              
291             Because $e-E<gt>response-E<gt>body is defined, the processing of view comes to
292             be passed by the operation of Egg.
293              
294             The content of the returned HASH reference is as follows.
295              
296             =head3 is_success
297              
298             Succeeding in the request is true.
299              
300             =head3 status
301              
302             There is a status line obtained because of the response.
303              
304             =head3 content_type
305              
306             There is a contents type obtained because of the response.
307              
308             Instead, the default of the setting enters when the contents type is not obtained.
309              
310             =head3 content
311              
312             There is a content of contents obtained because of the response.
313              
314             =head3 error
315              
316             One the respondent error message enters when is_success is false.
317              
318             =head3 no_hit
319              
320             When not becoming a hit to cashe, it becomes true.
321              
322             =head2 output ( [URL], [OPTION] )
323              
324             Content is set directly to L<Egg::Response> based on information obtained by the
325             get method.
326              
327             The response header set here is as follows.
328              
329             =head3 X-CACHE-UA
330              
331             When no_hit is only false, it is set.
332             In a word, the thing that becomes a hit to cashe is shown.
333              
334             =head3 expires or last_modified
335              
336             It is set based on the setting.
337              
338             =head3 status
339              
340             The obtained status line is set.
341              
342             =head3 content_type
343              
344             The obtained contents type is set.
345              
346             =head2 delete ( [URL] )
347              
348             The data of URL is deleted from cashe.
349              
350             $e->delete('http://domainname/');
351              
352             =over 4
353              
354             =item * Alias = remove.
355              
356             =back
357              
358             =head2 cache ([LABEL_NAME])
359              
360             The cashe object set to 'cache_name' is returned usually.
361              
362             When LABEL_NAME is specified, an arbitrary model object is returned.
363              
364             my $cache= $e->cache_ua->cache('cache_label');
365              
366             =head1 SEE ALSO
367              
368             L<Egg::Release>,
369             L<Egg::Response>,
370             L<Egg::Plugin::LWP>,
371             L<Egg::Model::Cache>,
372              
373             =head1 AUTHOR
374              
375             Masatoshi Mizuno E<lt>lusheE<64>cpan.orgE<gt>
376              
377             =head1 COPYRIGHT AND LICENSE
378              
379             Copyright (C) 2008 by Bee Flag, Corp. E<lt>http://egg.bomcity.com/E<gt>, All Rights Reserved.
380              
381             This library is free software; you can redistribute it and/or modify
382             it under the same terms as Perl itself, either Perl version 5.8.6 or,
383             at your option, any later version of Perl 5 you may have available.
384              
385             =cut
386