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