File Coverage

blib/lib/Plack/Handler/CGI.pm
Criterion Covered Total %
statement 25 58 43.1
branch 2 20 10.0
condition 0 7 0.0
subroutine 5 12 41.6
pod 1 3 33.3
total 33 100 33.0


line stmt bran cond sub pod time code
1             package Plack::Handler::CGI;
2 1     1   208198 use strict;
  1         1  
  1         31  
3 1     1   3 use warnings;
  1         2  
  1         48  
4 1     1   580 use IO::Handle;
  1         4883  
  1         685  
5              
6             # copied from HTTP::Status
7             my %StatusCode = (
8             100 => 'Continue',
9             101 => 'Switching Protocols',
10             102 => 'Processing', # RFC 2518 (WebDAV)
11             103 => 'Early Hints',
12             200 => 'OK',
13             201 => 'Created',
14             202 => 'Accepted',
15             203 => 'Non-Authoritative Information',
16             204 => 'No Content',
17             205 => 'Reset Content',
18             206 => 'Partial Content',
19             207 => 'Multi-Status', # RFC 2518 (WebDAV)
20             300 => 'Multiple Choices',
21             301 => 'Moved Permanently',
22             302 => 'Found',
23             303 => 'See Other',
24             304 => 'Not Modified',
25             305 => 'Use Proxy',
26             307 => 'Temporary Redirect',
27             400 => 'Bad Request',
28             401 => 'Unauthorized',
29             402 => 'Payment Required',
30             403 => 'Forbidden',
31             404 => 'Not Found',
32             405 => 'Method Not Allowed',
33             406 => 'Not Acceptable',
34             407 => 'Proxy Authentication Required',
35             408 => 'Request Timeout',
36             409 => 'Conflict',
37             410 => 'Gone',
38             411 => 'Length Required',
39             412 => 'Precondition Failed',
40             413 => 'Request Entity Too Large',
41             414 => 'Request-URI Too Large',
42             415 => 'Unsupported Media Type',
43             416 => 'Request Range Not Satisfiable',
44             417 => 'Expectation Failed',
45             422 => 'Unprocessable Entity', # RFC 2518 (WebDAV)
46             423 => 'Locked', # RFC 2518 (WebDAV)
47             424 => 'Failed Dependency', # RFC 2518 (WebDAV)
48             425 => 'No code', # WebDAV Advanced Collections
49             426 => 'Upgrade Required', # RFC 2817
50             449 => 'Retry with', # unofficial Microsoft
51             500 => 'Internal Server Error',
52             501 => 'Not Implemented',
53             502 => 'Bad Gateway',
54             503 => 'Service Unavailable',
55             504 => 'Gateway Timeout',
56             505 => 'HTTP Version Not Supported',
57             506 => 'Variant Also Negotiates', # RFC 2295
58             507 => 'Insufficient Storage', # RFC 2518 (WebDAV)
59             509 => 'Bandwidth Limit Exceeded', # unofficial
60             510 => 'Not Extended', # RFC 2774
61             );
62              
63 0     0 0 0 sub new { bless {}, shift }
64              
65             sub run {
66 0     0 0 0 my ($self, $app) = @_;
67              
68 0         0 my $env = $self->setup_env();
69              
70 0         0 my $res = $app->($env);
71 0 0       0 if (ref $res eq 'ARRAY') {
    0          
72 0         0 $self->_handle_response($res);
73             }
74             elsif (ref $res eq 'CODE') {
75             $res->(sub {
76 0     0   0 $self->_handle_response($_[0]);
77 0         0 });
78             }
79             else {
80 0         0 die "Bad response $res";
81             }
82             }
83              
84             sub setup_env {
85 0     0 1 0 my ( $self, $override_env ) = @_;
86              
87 0   0     0 $override_env ||= {};
88              
89 0         0 binmode STDIN;
90 0         0 binmode STDERR;
91              
92             my $env = {
93             %ENV,
94             'psgi.version' => [ 1, 1 ],
95             'psgi.url_scheme' => ($ENV{HTTPS}||'off') =~ /^(?:on|1)$/i ? 'https' : 'http',
96             'psgi.input' => *STDIN,
97             'psgi.errors' => *STDERR,
98             'psgi.multithread' => 0,
99             'psgi.multiprocess' => 1,
100             'psgi.run_once' => 1,
101             'psgi.streaming' => 1,
102             'psgi.nonblocking' => 1,
103 0 0 0     0 %{ $override_env },
  0         0  
104             };
105              
106 0         0 delete $env->{HTTP_CONTENT_TYPE};
107 0         0 delete $env->{HTTP_CONTENT_LENGTH};
108 0   0     0 $env->{'HTTP_COOKIE'} ||= $ENV{COOKIE}; # O'Reilly server bug
109              
110 0 0       0 if (!exists $env->{PATH_INFO}) {
111 0         0 $env->{PATH_INFO} = '';
112             }
113              
114 0 0       0 if ($env->{SCRIPT_NAME} eq '/') {
115 0         0 $env->{SCRIPT_NAME} = '';
116 0         0 $env->{PATH_INFO} = '/' . $env->{PATH_INFO};
117             }
118              
119 0         0 return $env;
120             }
121              
122              
123              
124             sub _handle_response {
125 1     1   9 my ($self, $res) = @_;
126              
127 1         6 *STDOUT->autoflush(1);
128 1         35 binmode STDOUT;
129              
130 1         1 my $hdrs;
131 1         2 my $message = $StatusCode{$res->[0]};
132 1         2 $hdrs = "Status: $res->[0] $message\015\012";
133              
134 1         2 my $headers = $res->[1];
135 1         5 while (my ($k, $v) = splice(@$headers, 0, 2)) {
136 0         0 $hdrs .= "$k: $v\015\012";
137             }
138 1         1 $hdrs .= "\015\012";
139              
140 1         54 print STDOUT $hdrs;
141              
142 1         20 my $body = $res->[2];
143 1     1   5 my $cb = sub { print STDOUT $_[0] };
  1         38  
144              
145             # inline Plack::Util::foreach here
146 1 50       6 if (ref $body eq 'ARRAY') {
    0          
147 1         3 for my $line (@$body) {
148 1 50       4 $cb->($line) if length $line;
149             }
150             }
151             elsif (defined $body) {
152 0 0         local $/ = \65536 unless ref $/;
153 0           while (defined(my $line = $body->getline)) {
154 0 0         $cb->($line) if length $line;
155             }
156 0           $body->close;
157             }
158             else {
159 0           return Plack::Handler::CGI::Writer->new;
160             }
161             }
162              
163             package Plack::Handler::CGI::Writer;
164 0     0     sub new { bless \do { my $x }, $_[0] }
  0            
165 0     0     sub write { print STDOUT $_[1] }
166       0     sub close { }
167              
168             package Plack::Handler::CGI;
169              
170             1;
171             __END__