File Coverage

lib/MooseX/Fastly/Role.pm
Criterion Covered Total %
statement 12 69 17.3
branch 0 24 0.0
condition 0 7 0.0
subroutine 4 12 33.3
pod 2 2 100.0
total 18 114 15.7


line stmt bran cond sub pod time code
1             package MooseX::Fastly::Role;
2             $MooseX::Fastly::Role::VERSION = '0.04';
3 1     1   404903 use Moose::Role;
  1         3797  
  1         3  
4 1     1   4638 use Net::Fastly 1.08;
  1         126630  
  1         27  
5 1     1   7 use Carp;
  1         3  
  1         43  
6 1     1   410 use HTTP::Tiny;
  1         8683  
  1         554  
7              
8             requires 'config'; # Where we can read our config from?!?
9              
10             =head1 NAME
11              
12             MooseX::Fastly::Role - Fastly api from config, and purge methods
13              
14             =head1 SYSOPSIS
15              
16             package My::App::CDN::Manager;
17              
18             use Moose;
19              
20             has config => (
21             is => 'ro',
22             isa => 'HashRef',
23             lazy => 1,
24             default => sub {
25             {
26             fastly_api_key => 'XXXXX',
27             fastly_service_id => 'YYYYY',
28             };
29             },
30             );
31              
32             with 'MooseX::Fastly::Role';
33              
34             $self->cdn_purge_now({
35             keys => [ 'foo', 'bar' ],
36             soft_purge => 1,
37             });
38              
39             $self->cdn_purge_all();
40              
41             my $fastly = $self->cdn_api();
42             my $services = $self->cdn_services();
43              
44             =head1 DESCRIPTION
45              
46             L<Fastly|https://www.fastly.com/> is a global CDN (Content Delivery Network),
47             used by many companies. This module requires a C<config> method to return
48             a hashref. This packages uses L<HTTP::Tiny> for most calls (so that you can
49             use Fastly's token authentication for purging keys), but also provides
50             accessors to L<Net::Fastly> for convenience.
51              
52             =head1 METHODS
53              
54             =head2 cdn_purge_now
55              
56             $self->cdn_purge_now({
57             keys => [ 'foo', 'bar' ],
58             soft_purge => 1,
59             });
60              
61             Purge is called on all services, for each key.
62              
63             =cut
64              
65             sub cdn_purge_now {
66 0     0 1   my ( $self, $args ) = @_;
67              
68 0           my $services = $self->_cdn_service_ids_from_config();
69              
70 0           foreach my $service_id ( @{$services} ) {
  0            
71 0 0         foreach my $key ( @{ $args->{keys} || [] } ) {
  0            
72 0           my $url = "/service/${service_id}/purge/${key}";
73 0           $self->_call_fastly_http_client( $url, $args->{soft_purge} );
74             }
75             }
76              
77 0           return 1;
78             }
79              
80             sub _call_fastly_http_client {
81 0     0     my ( $self, $url, $soft_purge ) = @_;
82 0   0       $soft_purge ||= '0';
83              
84 0           my $full_url = 'https://api.fastly.com' . $url;
85              
86 0           $self->_log_fastly_call("Purging ${url}");
87              
88 0           my $http_requester = $self->_fastly_http_client();
89 0 0         return unless $http_requester;
90              
91 0           my $response = $http_requester->post( $full_url,
92             { 'Fastly-Soft-Purge' => $soft_purge, } );
93              
94 0 0 0       if ( !$response->{success} || $response->{content} !~ '"status": "ok"' ) {
95             $self->_log_fastly_call(
96 0   0       "Failed to purge: $full_url" . $response->{content} || '' );
97             }
98              
99             }
100              
101             sub _log_fastly_call {
102 0 0   0     if ( $ENV{DEBUG_FASTLY_CALLS} ) {
103 0           warn $_[1];
104             }
105             }
106              
107             =head2 cdn_purge_all
108              
109             $self->cdn_purge_all();
110              
111             Purge all is called on all services
112              
113             =cut
114              
115             sub cdn_purge_all {
116 0     0 1   my ( $self, $args ) = @_;
117              
118 0           my $services = $self->_cdn_service_ids_from_config();
119              
120 0           foreach my $service_id ( @{$services} ) {
  0            
121 0 0         foreach my $key ( @{ $args->{keys} || [] } ) {
  0            
122 0           my $url = "/service/${service_id}/purge_all";
123 0           $self->_call_fastly_http_client( $url, $args->{soft_purge} );
124             }
125             }
126              
127 0           return 1;
128             }
129              
130              
131             sub _cdn_service_ids_from_config {
132 0     0     my $self = $_[0];
133 0           my @service_ids;
134              
135 0           my $service_ids = $self->config->{fastly_service_id};
136              
137 0 0         return \@service_ids unless $service_ids;
138              
139             @service_ids
140 0 0         = ref($service_ids) eq 'ARRAY' ? @{$service_ids} : ($service_ids);
  0            
141 0           return \@service_ids;
142             }
143              
144             has '_fastly_http_client' => (
145             is => 'ro',
146             lazy_build => '_build__fastly_http_client',
147             );
148              
149             sub _build__fastly_http_client {
150 0     0     my $self = $_[0];
151              
152 0           my $token = $self->config->{fastly_api_key};
153 0 0         return unless $token;
154              
155 0           my $http_requester = HTTP::Tiny->new(
156             default_headers => {
157             'Fastly-Key' => $token,
158             'Accept' => 'application/json'
159             },
160             );
161 0           return $http_requester;
162             }
163              
164              
165             =head1 Net::Fastly
166              
167             Methods below return objects from Net::Fastly.
168              
169             =head2 cdn_api
170              
171             my $cdn_api = $self->cdn_api();
172              
173             If there is a B<fastly_api_key> in C<config> a C<Net::Fastly> instance is
174             created and returned. Otherwise undef is returned (so you can develope
175             safely if you do not set B<fastly_api_key> in the C<config>).
176              
177             =cut
178              
179             has 'cdn_api' => (
180             is => 'ro',
181             lazy_build => '_build_cdn_api',
182             );
183              
184             sub _build_cdn_api {
185 0     0     my $self = $_[0];
186              
187 0           my $api_key = $self->config->{fastly_api_key};
188 0 0         return undef unless $api_key;
189              
190             # We have the credentials, so must be on production
191 0           my $fastly = Net::Fastly->new( api_key => $api_key );
192 0           return $fastly;
193             }
194              
195              
196             =head2 cdn_services
197              
198             my $services = $self->cdn_services();
199              
200             An array reference of C<Net::Fastly::Service> objects, based on the
201             C<fastly_service_id> id(s) set in C<config>.
202              
203             The array reference will be empty if C<fastly_service_id> is not found
204             in C<config>.
205              
206             =cut
207              
208             has 'cdn_services' => (
209             is => 'ro',
210             lazy_build => '_build_cdn_services',
211             );
212              
213             sub _build_cdn_services {
214 0     0     my ( $self, $args ) = @_;
215              
216 0           my @services;
217              
218 0           my $service_ids = $self->config->{fastly_service_id};
219 0 0         return \@services unless $service_ids;
220              
221 0           my $cdn_api = $self->cdn_api();
222 0 0         return \@services unless $cdn_api;
223              
224             my @service_ids
225 0 0         = ref($service_ids) eq 'ARRAY' ? @{$service_ids} : ($service_ids);
  0            
226              
227 0           @services = map { $cdn_api->get_service($service_ids) } @service_ids;
  0            
228              
229 0           return \@services;
230             }
231              
232             =head1 AUTHOR
233              
234             Leo Lapworth <LLAP@cpan.org>
235              
236             =head1 LICENSE
237              
238             This program is free software; you can redistribute it and/or modify it under
239             the terms same as Perl 5.
240              
241             =cut
242              
243             1;