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

            
4
has 'nph';
5

            
6
sub run {
7
  my $self = shift;
8

            
9
  my $tx  = $self->build_tx;
10
  my $req = $tx->req->parse(\%ENV);
11
  $tx->local_port($ENV{SERVER_PORT})->remote_address($ENV{REMOTE_ADDR});
12

            
13
  # Request body (may block if we try to read too much)
14
  binmode STDIN;
15
  my $len = $req->headers->content_length;
16
  until ($req->is_finished) {
17
    my $chunk = ($len && $len < 131072) ? $len : 131072;
18
    last unless my $read = STDIN->read(my $buffer, $chunk, 0);
19
    $req->parse($buffer);
20
    last if ($len -= $read) <= 0;
21
  }
22

            
23
  # Handle request
24
  $self->emit(request => $tx);
25

            
26
  # Response start line
27
  STDOUT->autoflush(1);
28
  binmode STDOUT;
29
  my $res = $tx->res;
30
  return undef if $self->nph && !_write($res, 'get_start_line_chunk');
31

            
32
  # Response headers
33
  $res->fix_headers;
34
  my $code = $res->code    || 404;
35
  my $msg  = $res->message || $res->default_message;
36
  $res->headers->status("$code $msg") unless $self->nph;
37
  return undef unless _write($res, 'get_header_chunk');
38

            
39
  # Response body
40
  $tx->is_empty or _write($res, 'get_body_chunk') or return undef;
41

            
42
  # Finish transaction
43
  $tx->server_close;
44

            
45
  return $res->code;
46
}
47

            
48
sub _write {
49
  my ($res, $method) = @_;
50

            
51
  my $offset = 0;
52
  while (1) {
53

            
54
    # No chunk yet, try again
55
    sleep 1 and next unless defined(my $chunk = $res->$method($offset));
56

            
57
    # End of part
58
    last unless my $len = length $chunk;
59

            
60
    # Make sure we can still write
61
    $offset += $len;
62
    return undef unless STDOUT->opened;
63
    print STDOUT $chunk;
64
  }
65

            
66
  return 1;
67
}
68

            
69
1;
70

            
71
=encoding utf8
72

            
73
=head1 NAME
74

            
75
Mojo::Server::CGI - CGI server
76

            
77
=head1 SYNOPSIS
78

            
79
  use Mojo::Server::CGI;
80

            
81
  my $cgi = Mojo::Server::CGI->new;
82
  $cgi->unsubscribe('request')
83
  $cgi->on(request => sub {
84
    my ($cgi, $tx) = @_;
85

            
86
    # Request
87
    my $method = $tx->req->method;
88
    my $path   = $tx->req->url->path;
89

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

            
95
    # Resume transaction
96
    $tx->resume;
97
  });
98
  $cgi->run;
99

            
100
=head1 DESCRIPTION
101

            
102
L<Mojo::Server::CGI> is a simple and portable implementation of RFC 3875.
103

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

            
106
=head1 EVENTS
107

            
108
L<Mojo::Server::CGI> inherits all events from L<Mojo::Server>.
109

            
110
=head1 ATTRIBUTES
111

            
112
L<Mojo::Server::CGI> inherits all attributes from L<Mojo::Server> and
113
implements the following new ones.
114

            
115
=head2 nph
116

            
117
  my $bool = $cgi->nph;
118
  $cgi     = $cgi->nph($bool);
119

            
120
Activate non-parsed header mode.
121

            
122
=head1 METHODS
123

            
124
L<Mojo::Server::CGI> inherits all methods from L<Mojo::Server> and implements
125
the following new ones.
126

            
127
=head2 run
128

            
129
  my $status = $cgi->run;
130

            
131
Run CGI.
132

            
133
=head1 SEE ALSO
134

            
135
L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>.
136

            
137
=cut