File Coverage

blib/lib/Tie/Handle/HTTP.pm
Criterion Covered Total %
statement 75 90 83.3
branch 14 26 53.8
condition 1 3 33.3
subroutine 13 15 86.6
pod 1 1 100.0
total 104 135 77.0


line stmt bran cond sub pod time code
1             package Tie::Handle::HTTP;
2              
3 5     5   26774 use strict;
  5         6  
  5         138  
4 5     5   22 use warnings;
  5         8  
  5         103  
5              
6 5     5   15981 use LWP::UserAgent;
  5         332114  
  5         173  
7 5     5   57 use HTTP::Request;
  5         10  
  5         109  
8 5     5   29 use HTTP::Status;
  5         10  
  5         2259  
9 5     5   5248 use Errno qw(EIO EINVAL);
  5         12159  
  5         660  
10 5     5   5029 use Symbol;
  5         4690  
  5         338  
11              
12 5     5   24 use vars qw($VERSION);
  5         14  
  5         3736  
13             $VERSION = '0.02';
14              
15             sub DEBUGGING () { 0 }
16              
17             sub new {
18 0     0 1 0 my $class = shift;
19 0         0 my $uri = shift;
20              
21 0         0 my $symbol = Symbol::gensym;
22              
23 0         0 tie( *$symbol, __PACKAGE__, $uri );
24              
25 0         0 return $symbol;
26             }
27              
28             sub TIEHANDLE {
29 1     1   6493 my $class = shift;
30 1         30 my $uri = shift;
31              
32             # Add configurable options for UserAgent
33 1         48 my $ua = LWP::UserAgent->new( keep_alive => 5 );
34 1         14085 my $req = HTTP::Request->new( HEAD => $uri );
35 1         10159 my $res = $ua->request( $req );
36              
37 1 50       206260 return unless $res->is_success;
38              
39 1   33     37 my $self = bless {}, (ref $class || $class);
40              
41 1         5 $self->{length} = $res->header( 'Content-Length' );
42 1         48 $self->{pos} = 0;
43 1         5 $self->{ua} = $ua;
44 1         3 $self->{uri} = $uri;
45 1         4 $self->{eof} = 0;
46              
47 1         2 warn "URI: $uri reports length of $self->{length} bytes.\n" if DEBUGGING;
48              
49 1         44 return $self;
50             }
51              
52             sub READ {
53 12     12   55 my $self = shift;
54 12         19 my $buf = \$_[0]; shift;
  12         18  
55 12         26 my ($len, $offset) = @_;
56            
57 12 50       48 defined( $$buf ) or $$buf = '';
58 12 50       113 defined( $offset ) or $offset = 0;
59            
60 12         25 my $pos = $self->{pos};
61 12         30 my $uri = $self->{uri};
62            
63             # Implement this area of functionality
64 12 50       41 return unless ($len > 0);
65              
66             # Implement this area of functionality
67 12 50       29 return unless ($offset >= 0);
68              
69 12 50       36 return 0 if ($self->EOF);
70              
71 12         28 my $start = $pos;
72 12         24 my $end = $pos + $len - 1;
73              
74 12         16 warn "Requesting $start to $end bytes of $uri\n" if DEBUGGING;
75              
76 12         190 my $req = HTTP::Request->new(GET => $uri, [
77             Range => "bytes=$start-$end",
78             ], );
79              
80 12         2464 my $res = $self->{ua}->request( $req );
81              
82 12 50       528244 if ($res->is_error) {
83 0 0       0 if ($res->code eq RC_REQUEST_RANGE_NOT_SATISFIABLE) {
84 0         0 $self->{eof} = 1;
85 0         0 return 0;
86             }
87            
88 0         0 $! = EIO;
89 0         0 return;
90             }
91              
92 12         221 my $length = length( $res->content );
93              
94 12         171 $self->{pos} = $pos + $length;
95              
96             # Find out if read(2) clears to the end of the string or not
97 12         37 substr( $$buf, $offset, $length ) = $res->content;
98              
99 12         323 return $length;
100             }
101              
102             sub EOF {
103 19     19   41 my $self = shift;
104              
105 19 50       78 return 1 if $self->{eof};
106              
107 19 50       69 return unless $self->{length};
108              
109 19         102 return $self->{pos} >= $self->{length};
110             }
111              
112             sub GETC {
113 0     0   0 my $self = shift;
114              
115 0         0 $self->READ( my $buf, 1 );
116 0         0 return $buf;
117             }
118              
119             sub TELL {
120 14     14   1235 my $self = shift;
121              
122 14         72 return $self->{pos};
123             }
124              
125             sub SEEK {
126 8     8   7528 my $self = shift;
127 8         22 my ($offset, $whence) = @_;
128              
129 8 100       39 if ($whence == 1) {
    100          
130 6         15 $offset += $self->{pos};
131             }
132             elsif ($whence == 2) {
133 1         11 my $len = $self->{length};
134 1 50       10 if (defined( $len )) {
135 1         4 $offset += $len;
136             }
137             else {
138 0         0 $! = EINVAL;
139 0         0 return 0;
140             }
141             }
142              
143 8         17 $self->{pos} = $offset;
144 8         22 $self->{eof} = 0;
145 8         33 return 1;
146             }
147              
148             1;
149             __END__