File Coverage

blib/lib/FCGI/EV/Std.pm
Criterion Covered Total %
statement 24 57 42.1
branch 0 16 0.0
condition 0 7 0.0
subroutine 8 12 66.6
pod 0 2 0.0
total 32 94 34.0


line stmt bran cond sub pod time code
1             package FCGI::EV::Std;
2              
3 2     2   31901 use warnings;
  2         6  
  2         64  
4 2     2   10 use strict;
  2         4  
  2         59  
5 2     2   9 use Carp;
  2         7  
  2         146  
6              
7 2     2   1681 use version; our $VERSION = qv('1.3.3'); # update POD & Changes & README
  2         5490  
  2         13  
8              
9             # update DEPENDENCIES in POD & Makefile.PL & README
10 2     2   171 use Scalar::Util qw( weaken );
  2         4  
  2         204  
11              
12 2     2   2004 use if $INC{'CGI.pm'}, 'CGI::Stateless';
  2         17  
  2         13  
13              
14              
15 2         136 use constant HTTP_417_EXPECTATION_FAILED =>
16             "Status: 417 Expectation Failed\r\n"
17             . "Content-Type: text/html\r\n"
18             . "\r\n"
19             . '<html><head><title>417 Expectation Failed</title></head>'
20             . '<body><h1>Expectation Failed</h1>'
21             . '<p>Request entity too large or incomplete.</p></body></html>'
22 2     2   128 ;
  2         3  
23              
24 2     2   10 use constant MiB => 1*1024*1024; ## no critic (Capitalization)
  2         3  
  2         1035  
25              
26             our $BLOCKING = 1;
27             our $MAX_STDIN = MiB;
28             our $MAIN = \&main::main;
29             our $HUP = undef;
30              
31              
32             sub new {
33 0     0 0   my ($class, $server, $env) = @_;
34 0   0       my $len = $env->{CONTENT_LENGTH} || 0;
35 0           my $self = bless {
36             server => $server,
37             env => $env,
38             stdin => q{},
39             allow => $len <= $MAX_STDIN,
40             }, $class;
41 0           weaken($self->{server});
42 0           return $self;
43             }
44              
45             # No protection against reading STDIN larger than CONTENT_LENGTH - because
46             # FastCGI protocol FORBID this so web server shouldn't send so much data
47             # ( http://www.fastcgi.com/devkit/doc/fcgi-spec.html#S6.2 ).
48             #
49             # If huge files will be uploaded it MAY have sense to save STDIN to
50             # secure tempfile - but code which parse POST data from STDIN in CGI also
51             # shouldn't read all STDIN into memory, or this feature will not help.
52             sub stdin {
53 0     0 0   my ($self, $stdin, $is_eof) = @_;
54 0 0         if ($self->{allow}) {
55 0           $self->{stdin} .= $stdin;
56             }
57 0 0         if ($is_eof) {
58 0 0 0       if (length $self->{stdin} != ($self->{env}{CONTENT_LENGTH} || 0)) {
59 0           $self->{server}->stdout(HTTP_417_EXPECTATION_FAILED, 1);
60             }
61             else {
62 0           local *STDIN;
63 0 0         open STDIN, '<', \$self->{stdin} or die "open STDIN: $!\n";
64 0           local %ENV = %{ $self->{env} };
  0            
65 0 0         if ($INC{'CGI/Stateless.pm'}) {
66 0           local $CGI::Q = CGI::Stateless->new();
67 0           $self->_run();
68             }
69             else {
70 0           $self->_run();
71             }
72             }
73             }
74 0           return;
75             }
76              
77             sub _run {
78 0     0     my ($self) = @_;
79 0 0         if ($BLOCKING) {
80 0           local *STDOUT;
81 0           my $reply = q{};
82 0 0         open STDOUT, '>', \$reply or die "open STDOUT: $!\n";
83 0           $MAIN->();
84 0           $self->{server}->stdout($reply, 1);
85             }
86             else {
87 0           $MAIN->($self->{server});
88             }
89 0           return;
90             }
91              
92             sub DESTROY {
93 0     0     my ($self) = @_;
94 0 0 0       if (!$BLOCKING && $HUP) {
95 0           $HUP->($self->{server});
96             }
97 0           return;
98             }
99              
100              
101             1; # Magic true value required at end of module
102             __END__
103              
104             =head1 NAME
105              
106             FCGI::EV::Std - Handler class to use with FCGI::EV
107              
108              
109             =head1 VERSION
110              
111             This document describes FCGI::EV::Std version 1.3.3
112              
113              
114             =head1 SYNOPSIS
115              
116             use FCGI::EV::Std;
117              
118             # configuration example
119             $FCGI::EV::Std::BLOCKING = 0;
120             $FCGI::EV::Std::MAX_STDIN = 10*1024*1024;
121             $FCGI::EV::Std::MAIN = \&nonblocking_main;
122             $FCGI::EV::Std::HUP = \&hup;
123              
124             # for usage example see FCGI::EV module SYNOPSIS
125              
126             =head1 DESCRIPTION
127              
128             This module must be used together with FCGI::EV. It will handle CGI
129             requests received by FCGI::EV. Both blocking and non-blocking CGI request
130             handling supported.
131              
132             It will validate size of STDIN: do not accept size larger than configured
133             in $MAX_STDIN (1 MB by default), do not accept incomplete STDIN (less
134             than $ENV{CONTENT_LENGTH} bytes) - in both cases HTTP reply "417
135             Expectation Failed" will be returned to browser.
136              
137             In non-blocking mode it optionally may call user callback function if web
138             server disconnect before CGI sent it reply (to interrupt processing this
139             request, if possible).
140              
141             It compatible with CGI.pm (CGI.pm must be loaded before FCGI::EV::Std
142             to activate this feature, and you'll need CGI::Stateless module), but may
143             also work with other modules which parse CGI parameters - in this case
144             these modules must support work in persistent environment and user
145             probably has to re-initialize that module state between requests.
146              
147              
148             =head1 INTERFACE
149              
150             There no user-callable methods in this module. Instead, it will call user
151             functions.
152              
153             In default configuration it will work in blocking mode and
154             will call main::main() on each incoming request, with prepared %ENV,
155             STDIN and STDOUT, so user code may work just as usual CGI application.
156             Other CGI requests will not be processed until main::main() returns.
157             Data printed by main::main() to STDOUT will be sent to web server only
158             after main::main() returns.
159              
160             It also possible to configure FCGI::EV::Std to work in non-blocking mode.
161             In this case on each incoming requests it will call main::main($server),
162             where $server is FCGI::EV object. In this case main::main() shouldn't
163             do any blocking operations (like using SQL database) but may setup any
164             events (I/O, timer, etc.) using EV module and should returns quickly.
165             Other CGI requests will be processed in parallel while this CGI request
166             wait for events. After CGI will have some data to send, it should use
167             $server->stdout($data, $is_eof) method (if $server is still defined - it
168             may become undef if connection to web server related to this CGI request
169             was already closed). In addition, FCGI::EV::Std may be configured to call
170             any user function, say, main::hup($server) if connection to web server will
171             be closed before CGI sent it reply. WARNING! User shouldn't keep
172             non-weaken() references to $server in it code!
173              
174             See also L<FCGI::EV::Std::Nonblock> - it's helper module which make
175             writing non-blocking CGI ease.
176              
177             Use these global variables to configure FCGI::EV::Std:
178              
179             =over
180              
181             =item $FCGI::EV::Std::BLOCKING = 1
182              
183             If true, then user function set in $FCGI::EV::Std::MAIN will be called in
184             blocking mode and without any parameters.
185              
186             If false, then user function set in $FCGI::EV::Std::MAIN will be called in
187             non-blocking mode, with parameter $server. Also, if $FCGI::EV::Std::HUP set
188             to user function, then it will be called if connection to web server is
189             closed before CGI sent it reply.
190              
191             =item $FCGI::EV::Std::MAX_STDIN = 1*1024*1024
192              
193             Limit on STDIN size. Increase if you need to receive large files using POST.
194              
195             =item $FCGI::EV::Std::MAIN = \&main::main
196              
197             User function called to process (or start processing in non-blocking mode)
198             incoming CGI request.
199              
200             =item $FCGI::EV::Std::HUP = undef
201              
202             User function called only in non-blocking mode to
203             notify about closed connection and, if possible, interrupt current CGI
204             request.
205              
206             This function got one parameter - $server object. It's same $server as was
207             given to $FCGI::EV::Std::MAIN function when this request was started (this
208             is how user can identify which of currently executing requests was
209             interrupted). The $server object will be destroyed shortly after that.
210              
211             =back
212              
213             =head1 DIAGNOSTICS
214              
215             =over
216              
217             =item C<< open STDIN: %s >>
218              
219             =item C<< open STDOUT: %s >>
220              
221             If anybody will see that, then probably your perl is broken. :)
222              
223             =back
224              
225              
226             =head1 CONFIGURATION AND ENVIRONMENT
227              
228             FCGI::EV::Std requires no configuration files or environment variables.
229              
230              
231             =head1 DEPENDENCIES
232              
233             version
234              
235              
236             =head1 INCOMPATIBILITIES
237              
238             None reported.
239              
240              
241             =head1 BUGS AND LIMITATIONS
242              
243             No bugs have been reported.
244              
245             Please report any bugs or feature requests to
246             C<bug-fcgi-ev-std@rt.cpan.org>, or through the web interface at
247             L<http://rt.cpan.org>.
248              
249              
250             =head1 AUTHOR
251              
252             Alex Efros C<< <powerman-asdf@ya.ru> >>
253              
254              
255             =head1 LICENSE AND COPYRIGHT
256              
257             Copyright (c) 2009, Alex Efros C<< <powerman-asdf@ya.ru> >>. All rights reserved.
258              
259             This module is free software; you can redistribute it and/or
260             modify it under the same terms as Perl itself. See L<perlartistic>.
261              
262              
263             =head1 DISCLAIMER OF WARRANTY
264              
265             BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
266             FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
267             OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
268             PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
269             EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
270             WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
271             ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
272             YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
273             NECESSARY SERVICING, REPAIR, OR CORRECTION.
274              
275             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
276             WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
277             REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
278             LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
279             OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
280             THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
281             RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
282             FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
283             SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
284             SUCH DAMAGES.