File Coverage

blib/lib/Corona/Server.pm
Criterion Covered Total %
statement 9 9 100.0
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 12 12 100.0


line stmt bran cond sub pod time code
1             package Corona::Server;
2 2     2   28924 use strict;
  2         4  
  2         94  
3 2     2   136 use 5.008_001;
  2         9  
  2         115  
4              
5 2     2   13 use base qw( Net::Server::Coro );
  2         11  
  2         2773  
6             use Plack::Util;
7              
8             use constant HAS_AIO => !$ENV{PLACK_NO_SENDFILE} && eval "use Coro::AIO; 1";
9              
10             use HTTP::Status;
11             use Scalar::Util;
12             use List::Util qw(sum max);
13             use Plack::HTTPParser qw( parse_http_request );
14             use constant MAX_REQUEST_SIZE => 131072;
15              
16             sub process_request {
17             my $self = shift;
18              
19             my $fh = $self->{server}{client};
20              
21             my $env = {
22             SERVER_PORT => $self->{server}{port}[0],
23             SERVER_NAME => $self->{server}{host}[0],
24             SCRIPT_NAME => '',
25             REMOTE_ADDR => $self->{server}{peeraddr},
26             'psgi.version' => [ 1, 0 ],
27             'psgi.errors' => *STDERR,
28             'psgi.input' => $self->{server}{client},
29             'psgi.url_scheme' => 'http', # SSL support?
30             'psgi.nonblocking' => Plack::Util::TRUE,
31             'psgi.run_once' => Plack::Util::FALSE,
32             'psgi.multithread' => Plack::Util::TRUE,
33             'psgi.multiprocess' => Plack::Util::FALSE,
34             'psgi.streaming' => Plack::Util::TRUE,
35             'psgix.io' => $fh->fh,
36             };
37              
38             my $res = [ 400, [ 'Content-Type' => 'text/plain' ], [ 'Bad Request' ] ];
39              
40             my $buf = '';
41             while (1) {
42             my $read = $fh->readline("\015\012\015\012")
43             or last;
44             $buf .= $read;
45              
46             my $reqlen = parse_http_request($buf, $env);
47             if ($reqlen >= 0) {
48             $res = Plack::Util::run_app $self->{app}, $env;
49             last;
50             } elsif ($reqlen == -2) {
51             # incomplete, continue
52             } else {
53             last;
54             }
55             }
56              
57             if (ref $res eq 'ARRAY') {
58             # PSGI standard
59             $self->_write_response($res, $fh);
60             } elsif (ref $res eq 'CODE') {
61             # delayed return
62             my $cb = Coro::rouse_cb;
63             $res->(sub {
64             $self->_write_response(shift, $fh, $cb);
65             });
66             Coro::rouse_wait $cb;
67             }
68             }
69              
70             sub _write_response {
71             my($self, $res, $fh, $rouse_cb) = @_;
72              
73             my (@lines, $conn_value);
74              
75             while (my ($k, $v) = splice(@{$res->[1]}, 0, 2)) {
76             push @lines, "$k: $v\015\012";
77             if (lc $k eq 'connection') {
78             $conn_value = $v;
79             }
80             }
81              
82             unshift @lines, "HTTP/1.0 $res->[0] @{[ HTTP::Status::status_message($res->[0]) ]}\015\012";
83             push @lines, "\015\012";
84              
85             $fh->syswrite(join '', @lines);
86              
87             if (!defined $res->[2]) {
88             # streaming write
89             return Plack::Util::inline_object
90             write => sub { $fh->syswrite(join '', @_) },
91             close => $rouse_cb;
92             } elsif (HAS_AIO && Plack::Util::is_real_fh($res->[2])) {
93             my $length = -s $res->[2];
94             my $offset = 0;
95             while (1) {
96             my $sent = aio_sendfile( $fh->fh, $res->[2], $offset, $length - $offset );
97             $offset += $sent if $sent > 0;
98             last if $offset >= $length;
99             }
100             } else {
101             Plack::Util::foreach($res->[2], sub { $fh->syswrite(join '', @_) });
102             }
103              
104             $rouse_cb->() if $rouse_cb;
105             }
106              
107             1;
108              
109             __END__