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   880601 use strict;
  19         41  
  19         896  
3 19     19   130 use warnings;
  19         36  
  19         1487  
4             our $VERSION = '1.0054';
5              
6 19     19   9558 use Plack::Util::Accessor qw(body status);
  19         60  
  19         165  
7 19     19   141 use Carp ();
  19         33  
  19         368  
8 19     19   3856 use Cookie::Baker ();
  19         48894  
  19         483  
9 19     19   191 use Scalar::Util ();
  19         34  
  19         463  
10 19     19   4505 use HTTP::Headers::Fast;
  19         54436  
  19         616  
11 19     19   181 use URI::Escape ();
  19         35  
  19         20080  
12              
13 6     6 0 1237 sub code { shift->status(@_) }
14 6     6 0 478 sub content { shift->body(@_) }
15              
16             sub new {
17 41     41 1 2092271 my($class, $rc, $headers, $content) = @_;
18              
19 41         119 my $self = bless {}, $class;
20 41 100       240 $self->status($rc) if defined $rc;
21 41 100       118 $self->headers($headers) if defined $headers;
22 41 100       167 $self->body($content) if defined $content;
23              
24 41         164 $self;
25             }
26              
27             sub headers {
28 65     65 1 116 my $self = shift;
29              
30 65 100       166 if (@_) {
31 4         5 my $headers = shift;
32 4 100       16 if (ref $headers eq 'ARRAY') {
    100          
33 1 50       3 Carp::carp("Odd number of headers") if @$headers % 2 != 0;
34 1         25 $headers = HTTP::Headers::Fast->new(@$headers);
35             } elsif (ref $headers eq 'HASH') {
36 1         7 $headers = HTTP::Headers::Fast->new(%$headers);
37             }
38 4         125 return $self->{headers} = $headers;
39             } else {
40 61   66     432 return $self->{headers} ||= HTTP::Headers::Fast->new();
41             }
42             }
43              
44             sub cookies {
45 47     47 1 110 my $self = shift;
46 47 100       112 if (@_) {
47 1         5 $self->{cookies} = shift;
48             } else {
49 46   100     315 return $self->{cookies} ||= +{ };
50             }
51             }
52              
53 8     8 1 271 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 68 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 37 my $self = shift;
69 7         16 return $self->headers->header('Location' => @_);
70             }
71              
72             sub redirect {
73 3     3 1 15 my $self = shift;
74              
75 3 50       7 if (@_) {
76 3         6 my $url = shift;
77 3   100     11 my $status = shift || 302;
78 3         8 $self->location($url);
79 3         161 $self->status($status);
80             }
81              
82 3         6 return $self->location;
83             }
84              
85             sub finalize {
86 36     36 1 164 my $self = shift;
87 36 50       127 Carp::croak "missing status" unless $self->status();
88              
89 36         111 my $headers = $self->headers;
90 36         355 my @headers;
91             $headers->scan(sub{
92 17     17   340 my ($k,$v) = @_;
93 17         65 $v =~ s/\015\012[\040|\011]+/chr(32)/ge; # replace LWS with a single SP
  2         6  
94 17         455 $v =~ s/\015|\012//g; # remove CR and LF since the char is invalid here
95 17         69 push @headers, $k, $v;
96 36         377 });
97              
98 36         578 $self->_finalize_cookies(\@headers);
99              
100             return [
101 36         104 $self->status,
102             \@headers,
103             $self->_body,
104             ];
105             }
106              
107             sub to_app {
108 1     1 1 7 my $self = shift;
109 1     1   16 return sub { $self->finalize };
  1         7  
110             }
111              
112              
113             sub _body {
114 36     36   66 my $self = shift;
115 36         192 my $body = $self->body;
116 36 100       166 $body = [] unless defined $body;
117 36 100 66     212 if (!ref $body or Scalar::Util::blessed($body) && overload::Method($body, q("")) && !$body->can('getline')) {
      100        
      100        
118 15         315 return [ $body ];
119             } else {
120 21         387 return $body;
121             }
122             }
123              
124             sub _finalize_cookies {
125 36     36   78 my($self, $headers) = @_;
126              
127 36         60 foreach my $name ( keys %{ $self->cookies } ) {
  36         146  
128 6         16 my $val = $self->cookies->{$name};
129              
130 6         25 my $cookie = Cookie::Baker::bake_cookie( $name, $val );
131 6         560 push @$headers, 'Set-Cookie' => $cookie;
132             }
133             }
134              
135             1;
136             __END__