File Coverage

blib/lib/HTTP/Engine/Role/RequestBuilder/ReadBody.pm
Criterion Covered Total %
statement 44 44 100.0
branch 18 18 100.0
condition n/a
subroutine 9 9 100.0
pod n/a
total 71 71 100.0


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             package HTTP::Engine::Role::RequestBuilder::ReadBody;
4 56     56   52561 use Any::Moose '::Role';
  56         135  
  56         433  
5 56     56   32615 use Carp ();
  56         139  
  56         33299  
6              
7             requires "_handle_read_chunk";
8              
9             sub _read_init {
10 19     19   54 my ( $self, $read_state ) = @_;
11              
12 19         45 foreach my $key (qw/input_handle content_length/) {
13 37 100       348 Carp::confess "read initialization must set $key"
14             unless defined $read_state->{$key};
15             }
16              
17 18         144 return $read_state;
18             }
19              
20             sub _read_start {
21 13     13   26 my ( $self, $state ) = @_;
22 13         47 $state->{started} = 1;
23             }
24              
25             sub _read_to_end {
26 20     20   202 my ( $self, $state, $req ) = @_;
27              
28 20         69 my $content_length = $state->{content_length};
29              
30 20 100       103 if ($content_length > 0) {
31 15         72 $self->_read_all($state, $req);
32              
33             # paranoia against wrong Content-Length header
34 15         50 my $diff = $state->{content_length} - $state->{read_position};
35              
36 15 100       69 if ($diff) {
37 2 100       7 if ( $diff > 0) {
38 1         14 die "Wrong Content-Length value: " . $content_length;
39             } else {
40 1         24 die "Premature end of request body, $diff bytes remaining";
41             }
42             }
43             }
44             }
45              
46             sub _read_all {
47 16     16   71 my ( $self, $state, $req ) = @_;
48              
49 16         71 while (my $buffer = $self->_read($state) ) {
50 75         221 $self->_handle_read_chunk($state, $buffer, $req);
51             }
52             }
53              
54             sub _read {
55 92     92   17337 my ($self, $state) = @_;
56              
57 92 100       266 $self->_read_start($state) unless $state->{started};
58              
59 92         108 my ( $length, $pos ) = @{$state}{qw(content_length read_position)};
  92         189  
60              
61 92         149 my $remaining = $length - $pos;
62              
63 92         226 my $maxlength = $self->chunk_size;
64              
65             # Are we done reading?
66 92 100       272 if ($remaining <= 0) {
67 16         73 return;
68             }
69              
70 76 100       162 my $readlen = ($remaining > $maxlength) ? $maxlength : $remaining;
71              
72 76         162 my $rc = $self->_read_chunk($state, my $buffer, $readlen);
73              
74 76 100       728 if (defined $rc) {
75 75         156 $state->{read_position} += $rc;
76 75         270 return $buffer;
77             } else {
78 1         14 die "Unknown error reading input: $!";
79             }
80             }
81              
82             sub _read_chunk {
83 76     76   117 my ( $self, $state ) = ( shift, shift );
84              
85 76         108 my $handle = $state->{input_handle};
86              
87 76         166 $self->_io_read( $handle, @_ );
88             }
89              
90             sub _io_read {
91 76     76   144 my ( $self, $handle ) = ( shift, shift );
92              
93 76 100       529 Carp::confess "no handle" unless defined $handle;
94              
95 75         242 return $handle->read(@_);
96             }
97              
98             1;
99              
100             __END__