File Coverage

blib/lib/WARC/Record/Replay/HTTP/Message.pm
Criterion Covered Total %
statement 61 63 96.8
branch 20 22 90.9
condition n/a
subroutine 11 11 100.0
pod 2 2 100.0
total 94 98 95.9


line stmt bran cond sub pod time code
1             package WARC::Record::Replay::HTTP::Message; # -*- CPerl -*-
2              
3 3     3   72036 use strict;
  3         17  
  3         90  
4 3     3   17 use warnings;
  3         9  
  3         82  
5              
6 3     3   16 use Carp;
  3         6  
  3         197  
7 3     3   18 use Fcntl qw(:seek);
  3         6  
  3         501  
8              
9             require HTTP::Message;
10             our @ISA = qw(HTTP::Message);
11              
12 3     3   445 use WARC; *WARC::Record::Replay::HTTP::Message::VERSION = \$WARC::VERSION;
  3         8  
  3         186  
13              
14             require WARC::Record::Replay;
15              
16             BEGIN {
17 3     3   450 use WARC::Record::Replay::HTTP;
  3         7  
  3         186  
18             $WARC::Record::Replay::HTTP::Message::{$_} =
19             $WARC::Record::Replay::HTTP::{$_}
20 3     3   1969 for WARC::Record::Replay::HTTP::HTTP_PARSE_REs;
21             }
22              
23             sub _load_record {
24 68     68   119 my $ob = shift; # partially constructed request/response object
25 68         95 my $record = shift; # WARC::Record object
26 68         115 my $handle = shift; # open handle for reading record data or undef
27              
28 68         167 local *_;
29              
30 68         134 $ob->{_warc_record} = $record;
31              
32 68 100       156 if ($handle) {
33             # Read headers from $handle.
34             {
35 21         32 my @headers = ();
  21         42  
36 21         67 local $/ = "\012";
37 21         93 while (<$handle>) {
38 89         398 s/[\015\012]+$//;
39 89 100       377 if (m/^($HTTP__token):\s+(.*)/o) # $1 -- name $2 -- value
    100          
    50          
40 64         314 { push @headers, $1, $2 }
41             elsif (m/^(\s+\S.*)$/) # $1 -- continued value
42 4         22 { $headers[-1] .= $1 }
43 21         89 elsif (m/^$/) { last }
44 0         0 else { warn "unrecogized input: $_"; return undef }
  0         0  
45             }
46 21         37 local $HTTP::Headers::TRANSLATE_UNDERSCORE;
47 21         65 $ob->headers->push_header(@headers);
48             }
49              
50 21         1649 my $data_offset = tell *$handle;
51 21         68 $ob->{_warc_data_offset} = $data_offset;
52              
53             # Decide whether to read or defer loading the message body.
54 21 100       65 if ($record->field('Content-Length') == $data_offset) {
    100          
55             # There is no content. Set an empty message body.
56 13         38 $ob->content('')
57             } elsif (($record->field('Content-Length') - $data_offset)
58             < $WARC::Record::Replay::HTTP::Content_Deferred_Loading_Threshold) {
59             # After reading headers, the length of the remaining data is less than
60             # the deferred loading threshold. Load the message body immediately.
61 3         4 { local $/ = undef; $ob->content(<$handle>) } # slurp data
  3         12  
  3         10  
62             } else {
63             # Defer loading the message body.
64 5         34 $ob->{_warc_defer}{content} = 1
65             }
66             }
67              
68             bless $ob, 'WARC::Record::Replay::'.(ref $ob)
69 68 100       473 if scalar grep $ob->{_warc_defer}{$_}, keys %{$ob->{_warc_defer}};
  68         621  
70              
71 68         836 return $ob;
72             }
73              
74             sub _load_content {
75 6     6   12 my $self = shift;
76              
77             croak "loading content larger than maximum length"
78             unless (($self->{_warc_record}->field('Content-Length')
79             - $self->{_warc_data_offset})
80 6 100       22 < $WARC::Record::Replay::HTTP::Content_Maximum_Length);
81              
82 5         18 my $handle = $self->{_warc_record}->open_continued;
83 5 50       31 seek($handle, $self->{_warc_data_offset}, SEEK_SET) or confess "seek: $!";
84 5         16 { local $/ = undef; $self->SUPER::content(<$handle>) } # slurp data
  5         21  
  5         21  
85              
86 5         195 $self->{_warc_defer}{content} = 0;
87             }
88              
89             ## overridden methods for deferred message body loading
90             sub content {
91 18     18 1 71025 my $self = shift;
92              
93 18 100       76 $self->_load_content if $self->{_warc_defer}{content};
94              
95 17         66 return $self->SUPER::content(@_);
96             }
97              
98             sub content_ref {
99 8     8 1 16786 my $self = shift;
100              
101 8 100       29 $self->_load_content if $self->{_warc_defer}{content};
102              
103 8         32 return $self->SUPER::content_ref(@_);
104             }
105              
106             1;
107             __END__