File Coverage

blib/lib/Alien/Build/Plugin/Fetch/HTTPTiny.pm
Criterion Covered Total %
statement 32 78 41.0
branch 3 26 11.5
condition 4 26 15.3
subroutine 8 9 88.8
pod 1 1 100.0
total 48 140 34.2


line stmt bran cond sub pod time code
1             package Alien::Build::Plugin::Fetch::HTTPTiny;
2              
3 3     3   1556 use strict;
  3         9  
  3         90  
4 3     3   14 use warnings;
  3         6  
  3         79  
5 3     3   58 use 5.008004;
  3         10  
6 3     3   358 use Alien::Build::Plugin;
  3         6  
  3         23  
7 3     3   23 use File::Basename ();
  3         5  
  3         60  
8 3     3   14 use Alien::Build::Util qw( _ssl_reqs );
  3         56  
  3         179  
9 3     3   172 use Carp ();
  3         7  
  3         2460  
10              
11             # ABSTRACT: Plugin for fetching files using HTTP::Tiny
12             our $VERSION = '2.47'; # VERSION
13              
14              
15             has '+url' => '';
16              
17              
18             has ssl => 0;
19              
20             # ignored for compatability
21             has bootstrap_ssl => 1;
22              
23             sub init
24             {
25 9     9 1 35 my($self, $meta) = @_;
26              
27 9         27 $meta->add_requires('share' => 'HTTP::Tiny' => '0.044' );
28 9         23 $meta->add_requires('share' => 'URI' => 0 );
29              
30 9   66     21 $meta->prop->{start_url} ||= $self->url;
31 9         20 $self->url($meta->prop->{start_url});
32 9 50       19 $self->url || Carp::croak('url is a required property');
33              
34 9 100 66     21 if($self->url =~ /^https:/ || $self->ssl)
35             {
36 4         14 my $reqs = _ssl_reqs;
37 4         20 foreach my $mod (sort keys %$reqs)
38             {
39 8         50 $meta->add_requires('share' => $mod => $reqs->{$mod});
40             }
41             }
42              
43             $meta->register_hook( fetch => sub {
44 0     0   0 my($build, $url, %options) = @_;
45 0   0     0 $url ||= $self->url;
46              
47 0         0 my %headers;
48 0 0       0 if(my $headers = $options{http_headers})
49             {
50 0 0       0 if(ref $headers eq 'ARRAY')
51             {
52 0         0 my @headers = @$headers;
53 0         0 while(@headers)
54             {
55 0         0 my $key = shift @headers;
56 0         0 my $value = shift @headers;
57 0 0 0     0 unless(defined $key && defined $value)
58             {
59 0         0 $build->log("Fetch for $url with http_headers contains undef key or value");
60 0         0 next;
61             }
62 0         0 push @{ $headers{$key} }, $value;
  0         0  
63             }
64             }
65             else
66             {
67 0         0 $build->log("Fetch for $url with http_headers that is not an array reference");
68             }
69             }
70              
71 0   0     0 my $ua = HTTP::Tiny->new( agent => "Alien-Build/@{[ $Alien::Build::VERSION || 'dev' ]} " );
  0         0  
72 0         0 my $res = $ua->get($url, { headers => \%headers });
73              
74 0 0       0 unless($res->{success})
75             {
76 0   0     0 my $status = $res->{status} || '---';
77 0   0     0 my $reason = $res->{reason} || 'unknown';
78              
79 0         0 $build->log("$status $reason fetching $url");
80 0 0       0 if($status == 599)
81             {
82 0         0 $build->log("exception: $_") for split /\n/, $res->{content};
83              
84 0         0 my($can_ssl, $why_ssl) = HTTP::Tiny->can_ssl;
85 0 0       0 if(! $can_ssl)
86             {
87 0 0       0 if($res->{redirects}) {
88 0         0 foreach my $redirect (@{ $res->{redirects} })
  0         0  
89             {
90 0 0 0     0 if(defined $redirect->{headers}->{location} && $redirect->{headers}->{location} =~ /^https:/)
91             {
92 0         0 $build->log("An attempt at a SSL URL https was made, but your HTTP::Tiny does not appear to be able to use https.");
93 0         0 $build->log("Please see: https://metacpan.org/pod/Alien::Build::Manual::FAQ#599-Internal-Exception-errors-downloading-packages-from-the-internet");
94             }
95             }
96             }
97             }
98             }
99              
100 0         0 die "error fetching $url: $status $reason";
101             }
102              
103 0         0 my($type) = split /;/, $res->{headers}->{'content-type'};
104 0         0 $type = lc $type;
105 0         0 my $base = URI->new($res->{url});
106 0         0 my $filename = File::Basename::basename do { my $name = $base->path; $name =~ s{/$}{}; $name };
  0         0  
  0         0  
  0         0  
107              
108             # TODO: this doesn't get exercised by t/bin/httpd
109 0 0       0 if(my $disposition = $res->{headers}->{"content-disposition"})
110             {
111             # Note: from memory without quotes does not match the spec,
112             # but many servers actually return this sort of value.
113 0 0 0     0 if($disposition =~ /filename="([^"]+)"/ || $disposition =~ /filename=([^\s]+)/)
114             {
115 0         0 $filename = $1;
116             }
117             }
118              
119 0 0       0 if($type eq 'text/html')
120             {
121             return {
122             type => 'html',
123             base => $base->as_string,
124             content => $res->{content},
125 0         0 };
126             }
127             else
128             {
129             return {
130             type => 'file',
131             filename => $filename || 'downloadedfile',
132             content => $res->{content},
133 0   0     0 };
134             }
135              
136 9         70 });
137              
138 9         19 $self;
139             }
140              
141             1;
142              
143             __END__