File Coverage

blib/lib/Mojo/Server/PSGI.pm
Criterion Covered Total %
statement 37 37 100.0
branch 8 12 66.6
condition 4 7 57.1
subroutine 7 7 100.0
pod 2 2 100.0
total 58 65 89.2


line stmt bran cond sub pod time code
1             package Mojo::Server::PSGI;
2 2     2   535 use Mojo::Base 'Mojo::Server';
  2         4  
  2         11  
3              
4             sub run {
5 8     8 1 16 my ($self, $env) = @_;
6              
7 8         28 my $tx = $self->build_tx;
8 8         20 my $req = $tx->req->parse($env);
9 8         42 $tx->local_port($env->{SERVER_PORT})->remote_address($env->{REMOTE_ADDR});
10              
11             # Request body (may block if we try to read too much)
12 8         22 my $len = $env->{CONTENT_LENGTH};
13 8         21 until ($req->is_finished) {
14 2 50 33     11 my $chunk = ($len && $len < 131072) ? $len : 131072;
15 2 50       16 last unless my $read = $env->{'psgi.input'}->read(my $buffer, $chunk, 0);
16 2         28 $req->parse($buffer);
17 2 50       6 last if ($len -= $read) <= 0;
18             }
19              
20 8         30 $self->emit(request => $tx);
21              
22             # Response headers
23 8         24 my $res = $tx->res->fix_headers;
24 8         23 my $hash = $res->headers->to_hash(1);
25 8         17 my @headers;
26 8         22 for my $name (keys %$hash) { push @headers, $name, $_ for @{$hash->{$name}} }
  25         36  
  25         67  
27              
28             # PSGI response
29 8         33 my $io = Mojo::Server::PSGI::_IO->new(tx => $tx, empty => $tx->is_empty);
30 8   50     23 return [$res->code // 404, \@headers, $io];
31             }
32              
33             sub to_psgi_app {
34 12     12 1 30 my $self = shift;
35              
36             # Preload application and wrap it
37 12         38 $self->app->server($self);
38 8     8   1034 return sub { $self->run(@_) }
39 12         132 }
40              
41             package Mojo::Server::PSGI::_IO;
42 2     2   15 use Mojo::Base -base;
  2         4  
  2         12  
43              
44             # Finish transaction
45 7     7   7638 sub close { shift->{tx}->closed }
46              
47             sub getline {
48 13     13   17642 my $self = shift;
49              
50             # Empty
51 13 100       40 return undef if $self->{empty};
52              
53             # No content yet, try again later
54 12   100     34 my $chunk = $self->{tx}->res->get_body_chunk($self->{offset} //= 0);
55 12 50       27 return '' unless defined $chunk;
56              
57             # End of content
58 12 100       32 return undef unless length $chunk;
59              
60 6         10 $self->{offset} += length $chunk;
61 6         25 return $chunk;
62             }
63              
64             1;
65              
66             =encoding utf8
67              
68             =head1 NAME
69              
70             Mojo::Server::PSGI - PSGI server
71              
72             =head1 SYNOPSIS
73              
74             use Mojo::Server::PSGI;
75              
76             my $psgi = Mojo::Server::PSGI->new;
77             $psgi->unsubscribe('request')->on(request => sub ($psgi, $tx) {
78              
79             # Request
80             my $method = $tx->req->method;
81             my $path = $tx->req->url->path;
82              
83             # Response
84             $tx->res->code(200);
85             $tx->res->headers->content_type('text/plain');
86             $tx->res->body("$method request for $path!");
87              
88             # Resume transaction
89             $tx->resume;
90             });
91             my $app = $psgi->to_psgi_app;
92              
93             =head1 DESCRIPTION
94              
95             L allows L applications to run on all L compatible servers.
96              
97             See L for more.
98              
99             =head1 EVENTS
100              
101             L inherits all events from L.
102              
103             =head1 ATTRIBUTES
104              
105             L inherits all attributes from L.
106              
107             =head1 METHODS
108              
109             L inherits all methods from L and implements the following new ones.
110              
111             =head2 run
112              
113             my $res = $psgi->run($env);
114              
115             Run L.
116              
117             =head2 to_psgi_app
118              
119             my $app = $psgi->to_psgi_app;
120              
121             Turn L application into L application.
122              
123             =head1 SEE ALSO
124              
125             L, L, L.
126              
127             =cut