File Coverage

blib/lib/HTTP/Tiny/FileProtocol.pm
Criterion Covered Total %
statement 77 77 100.0
branch 16 16 100.0
condition 22 22 100.0
subroutine 14 14 100.0
pod n/a
total 129 129 100.0


line stmt bran cond sub pod time code
1             package HTTP::Tiny::FileProtocol;
2             $HTTP::Tiny::FileProtocol::VERSION = '0.07';
3             # ABSTRACT: Add support for file:// protocol to HTTP::Tiny
4              
5 9     9   682798 use strict;
  9         79  
  9         272  
6 9     9   49 use warnings;
  9         21  
  9         241  
7              
8 9     9   754 use HTTP::Tiny;
  9         51205  
  9         190  
9 9     9   52 use File::Basename;
  9         27  
  9         674  
10 9     9   4412 use File::Copy;
  9         30501  
  9         536  
11 9     9   3546 use File::stat;
  9         52797  
  9         48  
12 9     9   586 use Fcntl qw(S_IRUSR);
  9         21  
  9         352  
13 9     9   4387 use LWP::MediaTypes;
  9         143284  
  9         805  
14 9     9   92 use Carp;
  9         22  
  9         590  
15              
16 9     9   61 no warnings 'redefine';
  9         19  
  9         6195  
17              
18             my $orig = *HTTP::Tiny::get{CODE};
19             my $orig_mirror = *HTTP::Tiny::mirror{CODE};
20              
21             *HTTP::Tiny::get = sub {
22 12     12   9050 my ($self, $url, $args) = @_;
23              
24 12 100 100     401 @_ == 2 || (@_ == 3 && ref $args eq 'HASH')
      100        
25             or croak(q/Usage: $http->get(URL, [HASHREF])/ . "\n");
26              
27 9 100       53 if ( $url !~ m{\Afile://} ) {
28 2   100     12 return $self->$orig( $url, $args || {});
29             }
30              
31 7         13 my $success;
32 7         14 my $status = 599;
33 7         16 my $reason = 'Internal Exception';
34 7         16 my $content = '';
35 7         13 my $content_type = 'text/plain';
36              
37 7         30 (my $path = $url) =~ s{\Afile://}{};
38              
39 7         40 my $st = stat $path;
40              
41 7 100       1280 if ( !$st ) {
    100          
42 2         5 $status = 404;
43 2         5 $reason = 'File Not Found';
44 2         9 return _build_response( $url, $success, $status, $reason, $content, $content_type );
45             }
46             elsif ( not $st->cando( S_IRUSR ) ) {
47 1         7 $status = 403;
48 1         4 $reason = 'Permission Denied';
49 1         5 return _build_response( $url, $success, $status, $reason, $content, $content_type );
50             }
51              
52 4         98 my($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$filesize,
53             $atime,$mtime,$ctime,$blksize,$blocks)
54             = stat($path);
55              
56 4         513 $status = 200;
57 4         8 $success = 1;
58              
59             {
60 4         8 open my $fh, '<', $path;
  4         184  
61 4         37 local $/;
62 4         15 binmode $fh;
63              
64 4         99 $content = <$fh>;
65 4         38 close $fh;
66              
67 4         25 $content_type = LWP::MediaTypes::guess_media_type( $path );
68             }
69              
70 4         345 return _build_response( $url, $success, $status, $reason, $content, $content_type );
71             };
72              
73             *HTTP::Tiny::mirror = sub {
74 8     8   10228 my ($self, $url, $file, $args) = @_;
75              
76 8 100 100     403 @_ == 3 || (@_ == 4 && ref $args eq 'HASH')
      100        
77             or croak(q/Usage: $http->mirror(URL, FILE, [HASHREF])/ . "\n");
78              
79 5 100       24 if ( $url !~ m{\Afile://} ) {
80 2   100     11 return $self->$orig_mirror( $url, $file, $args || {});
81             }
82              
83 3   100     17 my $response = $self->get( $url, $args || {} );
84 3 100       11 return $response if !$response->{success};
85              
86 2         9 (my $path = $url) =~ s{\Afile://}{};
87 2         11 copy $path, $file;
88              
89 2         580 return $response;
90             };
91              
92             sub _build_response {
93 10     10   1809 my ($url, $success, $status, $reason, $content, $content_type) = @_;
94              
95 10         19 my $bytes;
96             {
97 9     9   72 use bytes;
  9         19  
  9         67  
  10         18  
98 10         22 $bytes = length $content;
99             }
100              
101 10 100 100     127 my $response = {
      100        
102             url => $url,
103             success => $success,
104             status => $status,
105             ( !$success ? (reason => $reason) : () ),
106             content => $content // '',
107             headers => {
108             'content-type' => $content_type,
109             'content-length' => $bytes // 0,
110             },
111             };
112              
113 10         98 return $response;
114             }
115              
116             1;
117              
118             __END__