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 2     2   55815 use strict;
  2         13  
  2         46  
4 2     2   8 use warnings;
  2         5  
  2         39  
5              
6 2     2   8 use Carp;
  2         3  
  2         125  
7 2     2   9 use Fcntl qw(:seek);
  2         11  
  2         305  
8              
9             require HTTP::Message;
10             our @ISA = qw(HTTP::Message);
11              
12 2     2   315 use WARC; *WARC::Record::Replay::HTTP::Message::VERSION = \$WARC::VERSION;
  2         5  
  2         121  
13              
14             require WARC::Record::Replay;
15              
16             BEGIN {
17 2     2   335 use WARC::Record::Replay::HTTP;
  2         5  
  2         100  
18             $WARC::Record::Replay::HTTP::Message::{$_} =
19             $WARC::Record::Replay::HTTP::{$_}
20 2     2   980 for WARC::Record::Replay::HTTP::HTTP_PARSE_REs;
21             }
22              
23             sub _load_record {
24 35     35   45 my $ob = shift; # partially constructed request/response object
25 35         45 my $record = shift; # WARC::Record object
26 35         46 my $handle = shift; # open handle for reading record data or undef
27              
28 35         66 local *_;
29              
30 35         58 $ob->{_warc_record} = $record;
31              
32 35 100       107 if ($handle) {
33             # Read headers from $handle.
34             {
35 21         25 my @headers = ();
  21         36  
36 21         56 local $/ = "\012";
37 21         77 while (<$handle>) {
38 89         300 s/[\015\012]+$//;
39 89 100       332 if (m/^($HTTP__token):\s+(.*)/o) # $1 -- name $2 -- value
    100          
    50          
40 64         227 { push @headers, $1, $2 }
41             elsif (m/^(\s+\S.*)$/) # $1 -- continued value
42 4         18 { $headers[-1] .= $1 }
43 21         31 elsif (m/^$/) { last }
44 0         0 else { warn "unrecogized input: $_"; return undef }
  0         0  
45             }
46 21         27 local $HTTP::Headers::TRANSLATE_UNDERSCORE;
47 21         57 $ob->headers->push_header(@headers);
48             }
49              
50 21         1453 my $data_offset = tell *$handle;
51 21         55 $ob->{_warc_data_offset} = $data_offset;
52              
53             # Decide whether to read or defer loading the message body.
54 21 100       53 if ($record->field('Content-Length') == $data_offset) {
    100          
55             # There is no content. Set an empty message body.
56 13         34 $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         8  
  3         10  
62             } else {
63             # Defer loading the message body.
64 5         12 $ob->{_warc_defer}{content} = 1
65             }
66             }
67              
68             bless $ob, 'WARC::Record::Replay::'.(ref $ob)
69 35 100       329 if scalar grep $ob->{_warc_defer}{$_}, keys %{$ob->{_warc_defer}};
  35         240  
70              
71 35         486 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       17 < $WARC::Record::Replay::HTTP::Content_Maximum_Length);
81              
82 5         17 my $handle = $self->{_warc_record}->open_continued;
83 5 50       25 seek($handle, $self->{_warc_data_offset}, SEEK_SET) or confess "seek: $!";
84 5         13 { local $/ = undef; $self->SUPER::content(<$handle>) } # slurp data
  5         18  
  5         21  
85              
86 5         163 $self->{_warc_defer}{content} = 0;
87             }
88              
89             ## overridden methods for deferred message body loading
90             sub content {
91 18     18 1 55489 my $self = shift;
92              
93 18 100       73 $self->_load_content if $self->{_warc_defer}{content};
94              
95 17         60 return $self->SUPER::content(@_);
96             }
97              
98             sub content_ref {
99 8     8 1 13763 my $self = shift;
100              
101 8 100       27 $self->_load_content if $self->{_warc_defer}{content};
102              
103 8         30 return $self->SUPER::content_ref(@_);
104             }
105              
106             1;
107             __END__