Newer Older
130 lines | 2.716kb
add files
Yuki Kimoto authored on 2014-03-26
1
package Mojo::Server::PSGI;
2
use Mojo::Base 'Mojo::Server';
3

            
4
sub run {
5
  my ($self, $env) = @_;
6

            
7
  my $tx  = $self->build_tx;
8
  my $req = $tx->req->parse($env);
9
  $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
  my $len = $env->{CONTENT_LENGTH};
13
  until ($req->is_finished) {
14
    my $chunk = ($len && $len < 131072) ? $len : 131072;
15
    last unless my $read = $env->{'psgi.input'}->read(my $buffer, $chunk, 0);
16
    $req->parse($buffer);
17
    last if ($len -= $read) <= 0;
18
  }
19

            
20
  # Handle request
21
  $self->emit(request => $tx);
22

            
23
  # Response headers
24
  my $res     = $tx->res->fix_headers;
25
  my $headers = $res->content->headers;
26
  my @headers;
27
  for my $name (@{$headers->names}) {
28
    push @headers, $name => $_ for map {@$_} $headers->header($name);
29
  }
30

            
31
  # PSGI response
32
  my $io = Mojo::Server::PSGI::_IO->new(tx => $tx, empty => $tx->is_empty);
33
  return [$res->code || 404, \@headers, $io];
34
}
35

            
36
sub to_psgi_app {
37
  my $self = shift;
38

            
39
  # Preload application and wrap it
40
  $self->app;
41
  return sub { $self->run(@_) }
42
}
43

            
44
package Mojo::Server::PSGI::_IO;
45
use Mojo::Base -base;
46

            
47
# Finish transaction
48
sub close { shift->{tx}->server_close }
49

            
50
sub getline {
51
  my $self = shift;
52

            
53
  # Empty
54
  return undef if $self->{empty};
55

            
56
  # No content yet, try again later
57
  my $chunk = $self->{tx}->res->get_body_chunk($self->{offset} //= 0);
58
  return '' unless defined $chunk;
59

            
60
  # End of content
61
  return undef unless length $chunk;
62

            
63
  $self->{offset} += length $chunk;
64
  return $chunk;
65
}
66

            
67
1;
68

            
69
=encoding utf8
70

            
71
=head1 NAME
72

            
73
Mojo::Server::PSGI - PSGI server
74

            
75
=head1 SYNOPSIS
76

            
77
  use Mojo::Server::PSGI;
78

            
79
  my $psgi = Mojo::Server::PSGI->new;
80
  $psgi->unsubscribe('request');
81
  $psgi->on(request => sub {
82
    my ($psgi, $tx) = @_;
83

            
84
    # Request
85
    my $method = $tx->req->method;
86
    my $path   = $tx->req->url->path;
87

            
88
    # Response
89
    $tx->res->code(200);
90
    $tx->res->headers->content_type('text/plain');
91
    $tx->res->body("$method request for $path!");
92

            
93
    # Resume transaction
94
    $tx->resume;
95
  });
96
  my $app = $psgi->to_psgi_app;
97

            
98
=head1 DESCRIPTION
99

            
100
L<Mojo::Server::PSGI> allows L<Mojo> applications to run on all PSGI
101
compatible servers.
102

            
103
See L<Mojolicious::Guides::Cookbook> for more.
104

            
105
=head1 EVENTS
106

            
107
L<Mojo::Server::PSGI> inherits all events from L<Mojo::Server>.
108

            
109
=head1 METHODS
110

            
111
L<Mojo::Server::PSGI> inherits all methods from L<Mojo::Server> and implements
112
the following new ones.
113

            
114
=head2 run
115

            
116
  my $res = $psgi->run($env);
117

            
118
Run L<PSGI>.
119

            
120
=head2 to_psgi_app
121

            
122
  my $app = $psgi->to_psgi_app;
123

            
124
Turn L<Mojo> application into L<PSGI> application.
125

            
126
=head1 SEE ALSO
127

            
128
L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>.
129

            
130
=cut