File Coverage

blib/lib/WARC/Record/Replay/HTTP/Message.pm
Criterion Covered Total %
statement 62 64 96.8
branch 20 22 90.9
condition n/a
subroutine 11 11 100.0
pod 2 2 100.0
total 95 99 95.9


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