File Coverage

blib/lib/HTTP/Engine/ResponseFinalizer.pm
Criterion Covered Total %
statement 48 48 100.0
branch 24 24 100.0
condition 18 20 90.0
subroutine 8 8 100.0
pod 0 1 0.0
total 98 101 97.0


line stmt bran cond sub pod time code
1             package HTTP::Engine::ResponseFinalizer;
2 32     32   3092 use strict;
  32         67  
  32         1117  
3 32     32   410 use warnings;
  32         65  
  32         752  
4 32     32   181 use Scalar::Util ();
  32         58  
  32         515  
5 32     32   155 use Carp ();
  32         75  
  32         558  
6 32     32   5286 use CGI::Simple::Cookie;
  32         28949  
  32         6861  
7              
8             sub finalize {
9 66     66 0 297 my ($class, $req, $res, $interface) = @_;
10 66 100       1588 Carp::confess 'argument missing: $res' unless $res;
11              
12             # protocol
13 60 100       583 $res->protocol( $req->protocol ) unless $res->protocol;
14              
15             # Content-Length
16 59 100       370 if ($res->body) {
17             # get the length from a filehandle
18 52 100 100     5515 if (
      66        
      66        
19             ref($res->body) eq 'GLOB' ||
20             ( Scalar::Util::blessed($res->body) && ($res->body->can('getline') || $res->body->can('read')) )
21             ) {
22 8         19 my $st_size = 7; # see perldoc -f stat
23 8         14 my $size = eval { (stat($res->body))[$st_size] };
  8         189  
24 8 100       73 if (defined $size) {
    100          
25 5         35 $res->content_length($size);
26             } elsif (!$interface->can_has_streaming) { # can_has_streaming for PSGI streaming response
27 2         68 die "Serving filehandle without a content-length($@)";
28             }
29             } else {
30 32     32   2643 use bytes;
  32         95  
  32         292  
31 44         277 $res->content_length(bytes::length($res->body));
32             }
33             } else {
34 7         40 $res->content_length(0);
35             }
36              
37             # Errors
38 57 100       17087 if ($res->status =~ /^(1\d\d|[23]04)$/) {
39 1         8 $res->headers->remove_header("Content-Length");
40 1         18 $res->body('');
41             }
42              
43 57 100       254 $res->content_type('text/html') unless $res->content_type;
44 57         2076 $res->header(Status => $res->status);
45              
46 57         2309 $class->_finalize_cookies($res);
47              
48             # HTTP/1.1's default Connection: close
49 57 100 100     669 if ($res->protocol && $res->protocol =~ m!1\.1! && !!!$res->header('Connection')) {
      100        
50 8         267 $res->header( Connection => 'close' );
51             }
52              
53 57 100 100     898 $res->body('') if ((defined $req->method) and ($req->method eq 'HEAD'));
54             }
55              
56             sub _finalize_cookies {
57 57     57   122 my ($class, $res) = @_;
58              
59 57         219 my $cookies = $res->cookies;
60 57         171 my @keys = keys %$cookies;
61 57 100       222 if (@keys) {
62 2         5 for my $name (@keys) {
63 5         228 my $val = $cookies->{$name};
64 5 100 100     55 my $cookie = (
65             Scalar::Util::blessed($val)
66             ? $val
67             : CGI::Simple::Cookie->new(
68             -name => $name,
69             -value => $val->{value},
70             -expires => $val->{expires},
71             -domain => $val->{domain},
72             -path => $val->{path},
73             -secure => ($val->{secure} || 0)
74             )
75             );
76              
77 5         616 $res->headers->push_header('Set-Cookie' => $cookie->as_string);
78             }
79             }
80             }
81              
82             1;