File Coverage

blib/lib/HTTP/Engine/ResponseFinalizer.pm
Criterion Covered Total %
statement 38 47 80.8
branch 11 22 50.0
condition 6 17 35.2
subroutine 8 8 100.0
pod 0 1 0.0
total 63 95 66.3


line stmt bran cond sub pod time code
1             package HTTP::Engine::ResponseFinalizer;
2 3     3   744 use strict;
  3         4  
  3         67  
3 3     3   9 use warnings;
  3         4  
  3         52  
4 3     3   10 use Scalar::Util ();
  3         3  
  3         29  
5 3     3   8 use Carp ();
  3         6  
  3         33  
6 3     3   1234 use CGI::Simple::Cookie;
  3         10528  
  3         314  
7              
8             sub finalize {
9 6     6 0 8 my ($class, $req, $res) = @_;
10 6 50       9 Carp::confess 'argument missing: $res' unless $res;
11              
12             # protocol
13 6 50       13 $res->protocol( $req->protocol ) unless $res->protocol;
14              
15             # Content-Length
16 6 50       11 if ($res->body) {
17             # get the length from a filehandle
18 6 50 33     10 if ((Scalar::Util::blessed($res->body) && $res->body->can('read')) || (ref($res->body) eq 'GLOB')) {
      33        
19 0         0 my $st_size = 7; # see perldoc -f stat
20 0 0       0 if (my $size = eval { (stat($res->body))[$st_size] }) {
  0         0  
21 0         0 $res->content_length($size);
22             } else {
23 0         0 die "Serving filehandle without a content-length($@)";
24             }
25             } else {
26 3     3   13 use bytes;
  3         5  
  3         14  
27 6         10 $res->content_length(bytes::length($res->body));
28             }
29             } else {
30 0         0 $res->content_length(0);
31             }
32              
33             # Errors
34 6 50       116 if ($res->status =~ /^(1\d\d|[23]04)$/) {
35 0         0 $res->headers->remove_header("Content-Length");
36 0         0 $res->body('');
37             }
38              
39 6 50       13 $res->content_type('text/html') unless $res->content_type;
40 6         29 $res->header(Status => $res->status);
41              
42 6         104 $class->_finalize_cookies($res);
43              
44             # HTTP/1.1's default Connection: close
45 6 50 33     105 if ($res->protocol && $res->protocol =~ m!1\.1! && !!!$res->header('Connection')) {
      33        
46 0         0 $res->header( Connection => 'close' );
47             }
48              
49 6 50 33     9 $res->body('') if ((defined $req->method) and ($req->method eq 'HEAD'));
50             }
51              
52             sub _finalize_cookies {
53 6     6   6 my ($class, $res) = @_;
54              
55 6         13 my $cookies = $res->cookies;
56 6         11 my @keys = keys %$cookies;
57 6 100       13 if (@keys) {
58 1         2 for my $name (@keys) {
59 1         2 my $val = $cookies->{$name};
60             my $cookie = (
61             Scalar::Util::blessed($val)
62             ? $val
63             : CGI::Simple::Cookie->new(
64             -name => $name,
65             -value => $val->{value},
66             -expires => $val->{expires},
67             -domain => $val->{domain},
68             -path => $val->{path},
69 1 50 50     18 -secure => ($val->{secure} || 0)
70             )
71             );
72              
73 1         198 $res->headers->push_header('Set-Cookie' => $cookie->as_string);
74             }
75             }
76             }
77              
78             1;