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   402609 use strict;
  19         78  
  19         502  
3 19     19   80 use warnings;
  19         31  
  19         807  
4             our $VERSION = '1.0049';
5              
6 19     19   6730 use Plack::Util::Accessor qw(body status);
  19         50  
  19         103  
7 19     19   111 use Carp ();
  19         32  
  19         230  
8 19     19   3071 use Cookie::Baker ();
  19         22144  
  19         287  
9 19     19   94 use Scalar::Util ();
  19         34  
  19         337  
10 19     19   3475 use HTTP::Headers::Fast;
  19         36543  
  19         508  
11 19     19   103 use URI::Escape ();
  19         37  
  19         15307  
12              
13 6     6 0 760 sub code { shift->status(@_) }
14 6     6 0 289 sub content { shift->body(@_) }
15              
16             sub new {
17 41     41 1 13767 my($class, $rc, $headers, $content) = @_;
18              
19 41         94 my $self = bless {}, $class;
20 41 100       186 $self->status($rc) if defined $rc;
21 41 100       92 $self->headers($headers) if defined $headers;
22 41 100       100 $self->body($content) if defined $content;
23              
24 41         104 $self;
25             }
26              
27             sub headers {
28 65     65 1 84 my $self = shift;
29              
30 65 100       114 if (@_) {
31 4         5 my $headers = shift;
32 4 100       15 if (ref $headers eq 'ARRAY') {
    100          
33 1 50       6 Carp::carp("Odd number of headers") if @$headers % 2 != 0;
34 1         8 $headers = HTTP::Headers::Fast->new(@$headers);
35             } elsif (ref $headers eq 'HASH') {
36 1         4 $headers = HTTP::Headers::Fast->new(%$headers);
37             }
38 4         99 return $self->{headers} = $headers;
39             } else {
40 61   66     305 return $self->{headers} ||= HTTP::Headers::Fast->new();
41             }
42             }
43              
44             sub cookies {
45 47     47 1 81 my $self = shift;
46 47 100       90 if (@_) {
47 1         3 $self->{cookies} = shift;
48             } else {
49 46   100     237 return $self->{cookies} ||= +{ };
50             }
51             }
52              
53 8     8 1 186 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 53 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 33 my $self = shift;
69 7         11 return $self->headers->header('Location' => @_);
70             }
71              
72             sub redirect {
73 3     3 1 12 my $self = shift;
74              
75 3 50       7 if (@_) {
76 3         4 my $url = shift;
77 3   100     8 my $status = shift || 302;
78 3         8 $self->location($url);
79 3         152 $self->status($status);
80             }
81              
82 3         7 return $self->location;
83             }
84              
85             sub finalize {
86 36     36 1 140 my $self = shift;
87 36 50       78 Carp::croak "missing status" unless $self->status();
88              
89 36         89 my $headers = $self->headers;
90 36         240 my @headers;
91             $headers->scan(sub{
92 17     17   282 my ($k,$v) = @_;
93 17         38 $v =~ s/\015\012[\040|\011]+/chr(32)/ge; # replace LWS with a single SP
  2         5  
94 17         62 $v =~ s/\015|\012//g; # remove CR and LF since the char is invalid here
95 17         42 push @headers, $k, $v;
96 36         220 });
97              
98 36         411 $self->_finalize_cookies(\@headers);
99              
100             return [
101 36         85 $self->status,
102             \@headers,
103             $self->_body,
104             ];
105             }
106              
107             sub to_app {
108 1     1 1 4 my $self = shift;
109 1     1   8 return sub { $self->finalize };
  1         4  
110             }
111              
112              
113             sub _body {
114 36     36   57 my $self = shift;
115 36         69 my $body = $self->body;
116 36 100       108 $body = [] unless defined $body;
117 36 100 66     224 if (!ref $body or Scalar::Util::blessed($body) && overload::Method($body, q("")) && !$body->can('getline')) {
      100        
      100        
118 15         237 return [ $body ];
119             } else {
120 21         310 return $body;
121             }
122             }
123              
124             sub _finalize_cookies {
125 36     36   66 my($self, $headers) = @_;
126              
127 36         42 foreach my $name ( keys %{ $self->cookies } ) {
  36         74  
128 6         12 my $val = $self->cookies->{$name};
129              
130 6         15 my $cookie = Cookie::Baker::bake_cookie( $name, $val );
131 6         381 push @$headers, 'Set-Cookie' => $cookie;
132             }
133             }
134              
135             1;
136             __END__