File Coverage

blib/lib/FCGI/EV/Std/Nonblock.pm
Criterion Covered Total %
statement 18 56 32.1
branch 0 16 0.0
condition n/a
subroutine 6 13 46.1
pod 3 5 60.0
total 27 90 30.0


line stmt bran cond sub pod time code
1             package FCGI::EV::Std::Nonblock;
2              
3 2     2   9638 use warnings;
  2         5  
  2         68  
4 2     2   9 use strict;
  2         4  
  2         59  
5 2     2   10 use Carp;
  2         3  
  2         159  
6              
7 2     2   17 use version; our $VERSION = qv('1.3.2'); # update POD & Changes & README
  2         4  
  2         14  
8              
9             # update DEPENDENCIES in POD & Makefile.PL & README
10 2     2   178 use Scalar::Util qw( weaken refaddr );
  2         4  
  2         106  
11              
12 2     2   11 use FCGI::EV::Std;
  2         4  
  2         1271  
13             $FCGI::EV::Std::BLOCKING= 0;
14             $FCGI::EV::Std::MAIN = \&new;
15             $FCGI::EV::Std::HUP = \&HUP;
16              
17             my $cb_start = \&main::START;
18             my $cb_pre = \&main::PRE;
19             my $cb_post = \&main::POST;
20             my $cb_error = \&main::ERROR;
21             #my $HUP = undef;
22              
23             my (%Active, %Server);
24              
25              
26             sub new {
27 0     0 0   my ($server) = @_;
28 0           my $self = bless {}, __PACKAGE__;
29 0           $Active{ refaddr($self) } = $server;
30 0           $Server{ refaddr($server) } = $self;
31 0           weaken( $Active{ refaddr($self) } );
32 0           $self->_wrapper($cb_start);
33 0           return;
34             }
35              
36             sub done {
37 0     0 1   my ($self) = @_;
38 0 0         if (exists $Active{ refaddr($self) }) {
39 0           my $server = delete $Active{ refaddr($self) };
40 0 0         if ($server) {
41 0           delete $Server{ refaddr($server) };
42 0           $server->stdout(q{}, 1);
43             }
44             }
45             else {
46 0           croak 'this request already done()';
47             }
48 0           return;
49             }
50              
51             sub HUP {
52 0     0 0   my ($server) = @_;
53 0 0         return if !$server; # may happens during global destruction
54 0 0         if (exists $Server{ refaddr($server) }) {
55 0           my $self = delete $Server{ refaddr($server) };
56             # $HUP && $HUP->($self);
57             }
58 0           return;
59             }
60              
61             sub send { ## no critic (ProhibitBuiltinHomonyms)
62 0     0 1   my ($self, $buf) = @_;
63 0           my $server = $Active{ refaddr($self) };
64 0 0         if ($server) {
65 0           $server->stdout($buf, 0);
66             }
67 0           return;
68             }
69              
70             sub wrap_cb {
71 0     0 1   my ($self, $cb, @p) = @_;
72 0           weaken(my $this = $self);
73 0 0   0     return sub { $this && $this->_wrapper($cb, @p, @_) };
  0            
74             }
75              
76             sub _wrapper {
77 0     0     my ($this, $cb, @p) = @_;
78              
79 0           $cb_pre->($this);
80 0 0         my $err = eval { $cb->($this, @p); 1 } ? undef : $@;
  0            
  0            
81 0           $cb_post->($this);
82              
83 0 0         if (defined $err) {
84 0           $cb_error->($this, $err);
85             }
86 0           return;
87             }
88              
89              
90             1; # Magic true value required at end of module
91             __END__
92              
93             =head1 NAME
94              
95             FCGI::EV::Std::Nonblock - Ease non-blocking CGI using FCGI::EV::Std
96              
97              
98             =head1 VERSION
99              
100             This document describes FCGI::EV::Std::Nonblock version 1.3.2
101              
102              
103             =head1 SYNOPSIS
104              
105             use FCGI::EV;
106             use FCGI::EV::Std;
107             use FCGI::EV::Std::Nonblock; # just loading module will activate it!
108              
109             FCGI::EV->new($sock, 'FCGI::EV::Std');
110              
111             #
112             # Example CGI with FCGI::EV::Std::Nonblock interface
113             #
114            
115             sub PRE {}
116             sub POST {}
117             sub ERROR {}
118             sub START {
119             my ($this) = @_;
120             $this->{timer} = EV::timer 1, 0, $this->wrap_cb(\&reply);
121             }
122              
123             sub reply {
124             my ($this) = @_;
125             $this->send("Status: 200 OK\r\n");
126             $this->send("Content-Type: text/plain\r\n\r\n");
127             $this->send("Reply after 1 sec!");
128             $this->done();
129             return;
130             }
131              
132              
133             =head1 DESCRIPTION
134              
135             This module will made use of L<FCGI::EV::Std> in non-blocking mode ease for
136             user. To activate it it's enough to load that module - it will
137             automatically reconfigure FCGI::EV::Std and that result in calling user
138             code on incoming CGI requests in completely different way than explained
139             in L<FCGI::EV::Std> documentation.
140              
141              
142             =head1 INTERFACE
143              
144             This module will configure $BLOCKING, $MAIN and $HUP variables in
145             FCGI::EV::Std, so only user-configurable variable left is $MAX_STDIN
146             (see L<FCGI::EV::Std> documentation for details).
147              
148             On incoming CGI request this module will call user function
149             main::START($this). The $this parameter is object related to ... this :)
150             CGI request. This object has several methods listed below, but no fields -
151             user can use $this as usual HASHREF to store ANY data related to this request.
152              
153             To keep access to $this when user need to delay processing of this CGI
154             request until some event happens, user should generate callback for that event
155             in special way - using $this->wrap_cb($callback, @params) method.
156             This way when event happens $callback->($this, @params, @event_params)
157             will be called, and user will have $this.
158              
159             User should send reply to web server using $this->send($data) and
160             $this->done() methods.
161              
162             There also 3 another predefined functions which user must define: main::PRE,
163             main::POST and main::ERROR. The PRE($this) and POST($this) will be called
164             before and after user's main::START and $callback prepared using
165             $this->wrap_cb() - you can use these hooks to setup some environment which
166             all your callbacks need and make some cleanup after them. The ERROR($this, $@)
167             will be called if main::START or $callback will throw exception.
168             Exceptions within PRE, POST and ERROR will not be intercepted and will
169             kill your process.
170              
171             =over
172              
173             =item send( $data )
174              
175             Will send $data as (part of) CGI reply. Can be called any amount of times
176             before done() was called.
177              
178             Return nothing.
179              
180             =item done()
181              
182             Will finish processing current request. WARNING! User shouldn't keep
183             references to $this after calling done()!
184              
185             Return nothing.
186              
187             =item wrap_cb( $callback, @params )
188              
189             Will generate special CODEREF which, when called, will result in calling
190             $callback->($this, @params, @callback_params). User must ALWAYS use this way
191             of generating callbacks for event watchers to not lose access to $this
192             in event handlers, automatically execute main::PRE and main::POST hooks
193             before and after $callback, and intercept exceptions in $callback (which
194             will be automatically delivered to main::ERROR hook after executing POST
195             hook.
196              
197             The PRE and POST hooks will have only parameter: $this.
198             The ERROR hook will two parameters: $this and $exception (stored copy of $@).
199              
200             =back
201              
202              
203             =head1 DIAGNOSTICS
204              
205             None.
206              
207              
208             =head1 CONFIGURATION AND ENVIRONMENT
209              
210             FCGI::EV::Std::Nonblock requires no configuration files or environment variables.
211              
212              
213             =head1 DEPENDENCIES
214              
215             version
216              
217              
218             =head1 INCOMPATIBILITIES
219              
220             None reported.
221              
222              
223             =head1 BUGS AND LIMITATIONS
224              
225             No bugs have been reported.
226              
227             Please report any bugs or feature requests to
228             C<bug-fcgi-ev-std-nonblock@rt.cpan.org>, or through the web interface at
229             L<http://rt.cpan.org>.
230              
231              
232             =head1 AUTHOR
233              
234             Alex Efros C<< <powerman-asdf@ya.ru> >>
235              
236              
237             =head1 LICENSE AND COPYRIGHT
238              
239             Copyright (c) 2009, Alex Efros C<< <powerman-asdf@ya.ru> >>. All rights reserved.
240              
241             This module is free software; you can redistribute it and/or
242             modify it under the same terms as Perl itself. See L<perlartistic>.
243              
244              
245             =head1 DISCLAIMER OF WARRANTY
246              
247             BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
248             FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
249             OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
250             PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
251             EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
252             WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
253             ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
254             YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
255             NECESSARY SERVICING, REPAIR, OR CORRECTION.
256              
257             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
258             WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
259             REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
260             LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
261             OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
262             THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
263             RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
264             FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
265             SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
266             SUCH DAMAGES.