File Coverage

blib/lib/Plack/Response.pm
Criterion Covered Total %
statement 83 85 97.6
branch 21 24 87.5
condition 14 16 87.5
subroutine 23 25 92.0
pod 11 13 84.6
total 152 163 93.2


line stmt bran cond sub pod time code
1             package Plack::Response;
2 19     19   605789 use strict;
  19         28  
  19         641  
3 19     19   94 use warnings;
  19         27  
  19         1185  
4             our $VERSION = '1.0053';
5              
6 19     19   6486 use Plack::Util::Accessor qw(body status);
  19         73  
  19         106  
7 19     19   74 use Carp ();
  19         32  
  19         201  
8 19     19   2934 use Cookie::Baker ();
  19         34948  
  19         320  
9 19     19   119 use Scalar::Util ();
  19         23  
  19         271  
10 19     19   3393 use HTTP::Headers::Fast;
  19         38460  
  19         449  
11 19     19   75 use URI::Escape ();
  19         37  
  19         14197  
12              
13 6     6 0 875 sub code { shift->status(@_) }
14 6     6 0 281 sub content { shift->body(@_) }
15              
16             sub new {
17 41     41 1 1345355 my($class, $rc, $headers, $content) = @_;
18              
19 41         82 my $self = bless {}, $class;
20 41 100       188 $self->status($rc) if defined $rc;
21 41 100       84 $self->headers($headers) if defined $headers;
22 41 100       88 $self->body($content) if defined $content;
23              
24 41         106 $self;
25             }
26              
27             sub headers {
28 65     65 1 80 my $self = shift;
29              
30 65 100       117 if (@_) {
31 4         2 my $headers = shift;
32 4 100       31 if (ref $headers eq 'ARRAY') {
    100          
33 1 50       3 Carp::carp("Odd number of headers") if @$headers % 2 != 0;
34 1         9 $headers = HTTP::Headers::Fast->new(@$headers);
35             } elsif (ref $headers eq 'HASH') {
36 1         4 $headers = HTTP::Headers::Fast->new(%$headers);
37             }
38 4         85 return $self->{headers} = $headers;
39             } else {
40 61   66     317 return $self->{headers} ||= HTTP::Headers::Fast->new();
41             }
42             }
43              
44             sub cookies {
45 47     47 1 99 my $self = shift;
46 47 100       78 if (@_) {
47 1         3 $self->{cookies} = shift;
48             } else {
49 46   100     208 return $self->{cookies} ||= +{ };
50             }
51             }
52              
53 8     8 1 197 sub header { shift->headers->header(@_) } # shortcut
54              
55             sub content_length {
56 0     0 1 0 shift->headers->content_length(@_);
57             }
58              
59             sub content_type {
60 10     10 1 70 shift->headers->content_type(@_);
61             }
62              
63             sub content_encoding {
64 0     0 1 0 shift->headers->content_encoding(@_);
65             }
66              
67             sub location {
68 7     7 1 28 my $self = shift;
69 7         10 return $self->headers->header('Location' => @_);
70             }
71              
72             sub redirect {
73 3     3 1 19 my $self = shift;
74              
75 3 50       6 if (@_) {
76 3         4 my $url = shift;
77 3   100     7 my $status = shift || 302;
78 3         8 $self->location($url);
79 3         142 $self->status($status);
80             }
81              
82 3         4 return $self->location;
83             }
84              
85             sub finalize {
86 36     36 1 132 my $self = shift;
87 36 50       73 Carp::croak "missing status" unless $self->status();
88              
89 36         75 my $headers = $self->headers;
90 36         245 my @headers;
91             $headers->scan(sub{
92 17     17   283 my ($k,$v) = @_;
93 17         41 $v =~ s/\015\012[\040|\011]+/chr(32)/ge; # replace LWS with a single SP
  2         4  
94 17         58 $v =~ s/\015|\012//g; # remove CR and LF since the char is invalid here
95 17         43 push @headers, $k, $v;
96 36         304 });
97              
98 36         402 $self->_finalize_cookies(\@headers);
99              
100             return [
101 36         71 $self->status,
102             \@headers,
103             $self->_body,
104             ];
105             }
106              
107             sub to_app {
108 1     1 1 6 my $self = shift;
109 1     1   11 return sub { $self->finalize };
  1         4  
110             }
111              
112              
113             sub _body {
114 36     36   69 my $self = shift;
115 36         63 my $body = $self->body;
116 36 100       92 $body = [] unless defined $body;
117 36 100 66     142 if (!ref $body or Scalar::Util::blessed($body) && overload::Method($body, q("")) && !$body->can('getline')) {
      100        
      100        
118 15         238 return [ $body ];
119             } else {
120 21         292 return $body;
121             }
122             }
123              
124             sub _finalize_cookies {
125 36     36   50 my($self, $headers) = @_;
126              
127 36         43 foreach my $name ( keys %{ $self->cookies } ) {
  36         97  
128 6         10 my $val = $self->cookies->{$name};
129              
130 6         14 my $cookie = Cookie::Baker::bake_cookie( $name, $val );
131 6         353 push @$headers, 'Set-Cookie' => $cookie;
132             }
133             }
134              
135             1;
136             __END__