Commit 8f7eade1 authored by Xavier Guimard's avatar Xavier Guimard

Import original source of Net-Async-FastCGI 0.25

parents
use strict;
use warnings;
use Module::Build;
my $build = Module::Build->new(
module_name => 'Net::Async::FastCGI',
requires => {
'Encode' => 0,
'Exporter' => '5.57',
'HTTP::Request' => 0,
'HTTP::Response' => 0,
'IO::Async::Listener' => '0.35',
'IO::Async::Loop' => '0.16',
'IO::Async::Protocol::Stream' => '0.33',
'IO::Async::Test' => 0,
'Net::FastCGI::Constant' => '0.10',
'Net::FastCGI::Protocol' => '0.10',
'Tie::Handle' => 0,
},
build_requires => {
'Test::HexString' => 0,
'Test::More' => 0,
'Test::Refcount' => 0,
},
auto_configure_requires => 0, # Don't add M::B to configure_requires
license => 'perl',
create_makefile_pl => 'traditional',
create_license => 1,
create_readme => 1,
);
$build->create_build_script;
Revision history for Net-Async-FastCGI
0.25 CHANGES:
* Import PSGI support from FCGI::Async directly here
* Add some convenience methods to get often-used fields from request
without needing to use ->param
0.24 CHANGES:
* Correct SYNOPSIS examples to use ->listen rather than 'service'
param
* Import Exporter's 'import' function rather than 'use base'ing on
Exporter
0.23 CHANGES:
* Implement on_request as a normal IO::Async::Notifier-style event,
so it works as a subclass too
0.22 CHANGES:
* Split out from FCGI-Async; most code renamed
* Net::Async::FastCGI::Protocol directly built on top of
IO::Async::Protocol::Stream rather than overriding ::Stream
directly and replacing some methods
Revision history for FCGI-Async
0.21 CHANGES:
* Implement HTTP::Request/HTTP::Response gatewaying
* Implement PSGI gatewaying
* Provide Plack::Handler::FCGI::Async for plackup et.al.
* Implement ->stdin, ->stdout, ->stderr pseudo-filehandles
0.20 CHANGES:
* Use Net::FastCGI for low-level FastCGI constants and message
handling functions
* Ensure that ->set_encoding( undef ) actually works to disable the
encoding mechanism
BUGFIXES:
* Collect the entire PARAMS stream and only parse it when it's all
present, rather than piecewise
0.19 CHANGES:
* import Exporter::import instead of @ISAing it
* Respond with FCGI_UNKNOWN_TYPE or FCGI_UNKNOWN_ROLE when
appropriate (fixes RT 54480)
* Updated bundled example applications to a modern IO::Async style
0.18 CHANGES:
* Allow setting of per-request encoding for STDIN/STDOUT/STDERR
streams
* Code adjustment to make use of the new IO::Async::Listener class
* Deprecated ->listen( handle => IO ) in favour of ->new or
->configure instead.
0.17 CHANGES:
* Added 'use warnings'
* Documentation updates
* Various small updates to keep CPANTS happy
0.16 BUGFIXES:
* Support FCGI_GET_VALUES
(closes http://rt.cpan.org/Ticket/Display.html?id=43976)
* Use Test::HexString and wait_for_stream() during testing
0.15 BUGFIXES:
* Correctly handle webserver-aborted requests - silently discard
output.
0.14 CHANGES:
* Reworked constructor to use IO::Async::Loop->listen(). Allows
specifying a specific hostname.
* Added Request->stream_stdout_then_finish().
* Combine small stream writes into larger ones, to gain overhead
efficiences over the TCP socket.
BUGFIXES:
* Respect the FCGI_KEEP_CONN flag to close connections if required
0.13 CHANGES:
* Updated for IO::Async 0.11:
+ IO::Async::Set is now ::Loop
+ IO::Async::Buffer is now ::Stream
+ Use of $loop->watch_child() in examples rather than hand-coded
around watching SIGCHLD directly.
0.12 BUGFIXES:
* Updated to IO::Async::Buffer 0.10 (method/event renames)
0.11 CHANGES:
* Allow Request->finish() to take an exitcode
BUGFIXES:
* Cope with environment parameters longer than 127 bytes
* Small updates to included 'example' scripts
0.10 CHANGES:
* Added CGI->FastCGI gateway example
BUGFIXES:
* Better handling of ->read_stdin_line()
0.09: CHANGES:
* Added 'fortune' example
* Better testing of connection reuse
* Support printing to STDERR FastCGI stream
0.08: CHANGES:
* First version to be based on IO::Async
0.07: CHANGES:
* Changed build system from ExtUtils::MakeMaker to Module::Build
Versions before this did not appear on CPAN, and no 'Changes' notes are
provided for them.
This diff is collapsed.
Build.PL
Changes
examples/envtest.fcgi
examples/exec-cgi.fcgi
examples/fortune.fcgi
examples/mintest.fcgi
examples/sample.cgi
lib/Net/Async/FastCGI.pm
lib/Net/Async/FastCGI/Protocol.pm
lib/Net/Async/FastCGI/PSGI.pm
lib/Net/Async/FastCGI/Request.pm
lib/Net/Async/FastCGI/ServerProtocol.pm
lib/Plack/Handler/Net/Async/FastCGI.pm
LICENSE
Makefile.PL
MANIFEST This list of files
META.json
META.yml
psgifiles/counter.psgi
psgifiles/env.psgi
psgifiles/helloworld.psgi
psgifiles/sleepy.psgi
README
t/00use.t
t/01test.t
t/02request-minimal.t
t/03request-full.t
t/04request-reuse.t
t/05request-multiplex.t
t/06request-binary.t
t/07request-longparams.t
t/08request-shortwrites.t
t/09request-streamstdout.t
t/10request-close.t
t/11request-encoding.t
t/12request-unknown.t
t/13request-handles.t
t/20get_values.t
t/30request-HTTP.t
t/40psgi.t
t/41psgi-streaming.t
t/99pod.t
t/lib/TestFCGI.pm
{
"abstract" : "use FastCGI with L<IO::Async>",
"author" : [
"Paul Evans <leonerd@leonerd.org.uk>"
],
"dynamic_config" : 1,
"generated_by" : "Module::Build version 0.4001, CPAN::Meta::Converter version 2.120921",
"license" : [
"perl_5"
],
"meta-spec" : {
"url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
"version" : "2"
},
"name" : "Net-Async-FastCGI",
"prereqs" : {
"build" : {
"requires" : {
"Test::HexString" : "0",
"Test::More" : "0",
"Test::Refcount" : "0"
}
},
"runtime" : {
"requires" : {
"Encode" : "0",
"Exporter" : "5.57",
"HTTP::Request" : "0",
"HTTP::Response" : "0",
"IO::Async::Listener" : "0.35",
"IO::Async::Loop" : "0.16",
"IO::Async::Protocol::Stream" : "0.33",
"IO::Async::Test" : "0",
"Net::FastCGI::Constant" : "0.10",
"Net::FastCGI::Protocol" : "0.10",
"Tie::Handle" : "0"
}
}
},
"provides" : {
"Net::Async::FastCGI" : {
"file" : "lib/Net/Async/FastCGI.pm",
"version" : "0.25"
},
"Net::Async::FastCGI::PSGI" : {
"file" : "lib/Net/Async/FastCGI/PSGI.pm",
"version" : "0.25"
},
"Net::Async::FastCGI::Protocol" : {
"file" : "lib/Net/Async/FastCGI/Protocol.pm",
"version" : "0.25"
},
"Net::Async::FastCGI::Request" : {
"file" : "lib/Net/Async/FastCGI/Request.pm",
"version" : "0.25"
},
"Net::Async::FastCGI::ServerProtocol" : {
"file" : "lib/Net/Async/FastCGI/ServerProtocol.pm",
"version" : 0
},
"Plack::Handler::Net::Async::FastCGI" : {
"file" : "lib/Plack/Handler/Net/Async/FastCGI.pm",
"version" : "0.25"
}
},
"release_status" : "stable",
"resources" : {
"license" : [
"http://dev.perl.org/licenses/"
]
},
"version" : "0.25"
}
---
abstract: 'use FastCGI with L<IO::Async>'
author:
- 'Paul Evans <leonerd@leonerd.org.uk>'
build_requires:
Test::HexString: 0
Test::More: 0
Test::Refcount: 0
dynamic_config: 1
generated_by: 'Module::Build version 0.4001, CPAN::Meta::Converter version 2.120921'
license: perl
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
version: 1.4
name: Net-Async-FastCGI
provides:
Net::Async::FastCGI:
file: lib/Net/Async/FastCGI.pm
version: 0.25
Net::Async::FastCGI::PSGI:
file: lib/Net/Async/FastCGI/PSGI.pm
version: 0.25
Net::Async::FastCGI::Protocol:
file: lib/Net/Async/FastCGI/Protocol.pm
version: 0.25
Net::Async::FastCGI::Request:
file: lib/Net/Async/FastCGI/Request.pm
version: 0.25
Net::Async::FastCGI::ServerProtocol:
file: lib/Net/Async/FastCGI/ServerProtocol.pm
version: 0
Plack::Handler::Net::Async::FastCGI:
file: lib/Plack/Handler/Net/Async/FastCGI.pm
version: 0.25
requires:
Encode: 0
Exporter: 5.57
HTTP::Request: 0
HTTP::Response: 0
IO::Async::Listener: 0.35
IO::Async::Loop: 0.16
IO::Async::Protocol::Stream: 0.33
IO::Async::Test: 0
Net::FastCGI::Constant: 0.10
Net::FastCGI::Protocol: 0.10
Tie::Handle: 0
resources:
license: http://dev.perl.org/licenses/
version: 0.25
# Note: this file was auto-generated by Module::Build::Compat version 0.4001
use ExtUtils::MakeMaker;
WriteMakefile
(
'NAME' => 'Net::Async::FastCGI',
'VERSION_FROM' => 'lib/Net/Async/FastCGI.pm',
'PREREQ_PM' => {
'Encode' => 0,
'Exporter' => '5.57',
'HTTP::Request' => 0,
'HTTP::Response' => 0,
'IO::Async::Listener' => '0.35',
'IO::Async::Loop' => '0.16',
'IO::Async::Protocol::Stream' => '0.33',
'IO::Async::Test' => 0,
'Net::FastCGI::Constant' => '0.10',
'Net::FastCGI::Protocol' => '0.10',
'Test::HexString' => 0,
'Test::More' => 0,
'Test::Refcount' => 0,
'Tie::Handle' => 0
},
'INSTALLDIRS' => 'site',
'EXE_FILES' => [],
'PL_FILES' => {}
)
;
NAME
`Net::Async::FastCGI' - use FastCGI with IO::Async
SYNOPSIS
As an adapter:
use Net::Async::FastCGI;
use IO::Async::Loop;
my $loop = IO::Async::Loop->new();
my $fastcgi = Net::Async::FastCGI->new(
on_request => sub {
my ( $fastcgi, $req ) = @_;
# Handle the request here
}
);
$loop->add( $fastcgi );
$fastcgi->listen(
service => 1234,
on_resolve_error => sub { die "Cannot resolve - $_[-1]\n" },
on_listen_error => sub { die "Cannot listen - $_[-1]\n" },
);
$loop->run;
As a subclass:
package MyFastCGIResponder;
use base qw( Net::Async::FastCGI );
sub on_request
{
my $self = shift;
my ( $req ) = @_;
# Handle the request here
}
...
use IO::Async::Loop;
my $loop = IO::Async::Loop->new();
my $fastcgi;
$loop->add( $fastcgi = MyFastCGIResponder->new( service => 1234 ) );
$fastcgi->listen(
service => 1234,
on_resolve_error => sub { die "Cannot resolve - $_[-1]\n" },
on_listen_error => sub { die "Cannot listen - $_[-1]\n" },
);
$loop->run;
DESCRIPTION
This module allows a program to respond asynchronously to FastCGI
requests, as part of a program based on IO::Async. An object in this
class represents a single FastCGI responder that the webserver is
configured to communicate with. It can handle multiple outstanding
requests at a time, responding to each as data is provided by the
program. Individual outstanding requests that have been started but not
yet finished, are represented by instances of
Net::Async::FastCGI::Request.
EVENTS
The following events are invoked, either using subclass methods or CODE
references in parameters:
on_request $req
Invoked when a new FastCGI request is received. It will be passed a new
Net::Async::FastCGI::Request object.
PARAMETERS
The following named parameters may be passed to `new' or `configure':
on_request => CODE
CODE references for `on_request' event handler.
default_encoding => STRING
Sets the default encoding used by all new requests. If not
supplied then `UTF-8' will apply.
METHODS
$fcgi->listen( %args )
Start listening for connections on a socket, creating it first if
necessary.
This method may be called in either of the following ways. To listen on
an existing socket filehandle:
handle => IO
An IO handle referring to a listen-mode socket. This is now
deprecated; use the `handle' key to the `new' or `configure' methods
instead.
Or, to create the listening socket or sockets:
service => STRING
Port number or service name to listen on.
host => STRING
Optional. If supplied, the hostname will be resolved into a set of
addresses, and one listening socket will be created for each
address. If not, then all available addresses will be used.
This method may also require `on_listen_error' or `on_resolve_error'
callbacks for error handling - see IO::Async::Listener for more detail.
Limits in FCGI_GET_VALUES
The `FCGI_GET_VALUES' FastCGI request can enquire of the responder the
maximum number of connections or requests it can support. Because this
module puts no fundamental limit on these values, it will return some
arbitrary numbers. These are given in package variables:
$Net::Async::FastCGI::MAX_CONNS = 1024;
$Net::Async::FastCGI::MAX_REQS = 1024;
These variables are provided in case the containing application wishes
to make the library return different values in the request. These values
are not actually used by the library, other than to fill in the values
in response of `FCGI_GET_VALUES'.
Using a socket on STDIN
When running a local FastCGI responder, the webserver will create a new
INET socket connected to the script's STDIN file handle. To use the
socket in this case, it should be passed as the `handle' argument.
SEE ALSO
* CGI::Fast - Fast CGI drop-in replacement of CGI; single-threaded,
blocking mode.
* http://hoohoo.ncsa.uiuc.edu/cgi/interface.html - The Common Gateway
Interface Specification
* http://www.fastcgi.com/devkit/doc/fcgi-spec.html - FastCGI
Specification
AUTHOR
Paul Evans <leonerd@leonerd.org.uk>
#!/usr/bin/perl -w
use strict;
use IO::Async::Loop;
my $loop = IO::Async::Loop->new();
$loop->add( Example::EnvTestResponder->new( handle => \*STDIN ) );
$loop->run;
package Example::EnvTestResponder;
use base qw( Net::Async::FastCGI );
sub on_request
{
my $self = shift;
my ( $req ) = @_;
my $env = $req->params();
my $page = "";
my $path = $env->{PATH_INFO} || "/";
my $qs = $env->{QUERY_STRING} || "";
my %queryparams = map { m/^(.*?)=(.*)$/ && ( $1, $2 ) } split( m/&/, $qs );
$page = "<h1>Request Variables</h1>\n";
$page .= "<h2>Basics</h2>\n" .
"<p>Path: <tt>$path</tt></p>\n";
if ( keys %queryparams ) {
$page .= "<h2>Query parameters</h2>\n" .
"<table border=\"1\">\n";
foreach my $key ( sort keys %queryparams ) {
$page .= "<tr><td>$key</td><td><tt>$queryparams{$key}</tt></td></tr>\n";
}
$page .= "</table>\n";
}
$page .= "<h2>Environment variables</h2>\n";
$page .= "<table>\n";
foreach my $key ( sort keys %$env ) {
$page .= "<tr><td>$key</td><td><tt>$env->{$key}</tt></td></tr>\n";
}
$page .= "</table>\n";
$req->print_stdout(
"Content-type: text/html\r\n" .
"Content-length: " . length( $page ) . "\r\n" .
"\r\n" .
$page . "\r\n"
);
$req->finish();
}
#!/usr/bin/perl -w
use strict;
use Net::Async::FastCGI;
use IO::Async::Stream;
use IO::Async::Loop;
my $loop = IO::Async::Loop->new();
sub on_request
{
my ( $fcgi, $req ) = @_;
my %req_env = %{ $req->params };
# Determine these however you like; perhaps examine $req
my $handler = "./sample.cgi";
my @handler_args = ();
my $stdin = "";
while( defined( my $line = $req->read_stdin_line ) ) {
$stdin .= $line;
}
$fcgi->loop->open_child(
command => [ $handler, @handler_args ],
setup => [
env => \%req_env,
],
stdin => {
from => $stdin,
},
stdout => {
on_read => sub {
my ( undef, $buffref ) = @_;
$req->print_stdout( $$buffref );
$$buffref = "";
return 0;
},
},
stderr => {
on_read => sub {
my ( undef, $buffref ) = @_;
$req->print_stderr( $$buffref );
$$buffref = "";
return 0;
},
},
on_finish => sub {
my ( undef, $exitcode ) = @_;
$req->finish( $exitcode );
},
);
}
my $fcgi = Net::Async::FastCGI->new(
handle => \*STDIN,
on_request => \&on_request,
);
$loop->add( $fcgi );
$loop->run;
#!/usr/bin/perl -w
use strict;
use IO::Async::Loop;
my $FORTUNE = "/usr/games/fortune";
my $loop = IO::Async::Loop->new();
$loop->add( Example::FortuneResponder->new( handle => \*STDIN ) );
$loop->run;
package Example::FortuneResponder;
use base qw( Net::Async::FastCGI );
use IO::Async::Stream;
sub on_request
{
my $self = shift;
my ( $req ) = @_;
my $kid = $self->loop->open_child(
command => [ $FORTUNE ],
stdout => {
on_read => sub {
my ( undef, $buffref, $closed ) = @_;
if( $$buffref =~ s{^(.*?)\n}{} ) {
$req->print_stdout( "<p>$1</p>" );
return 1;
}
if( $closed ) {
# Deal with a final partial line the child may have written
$req->print_stdout( "<p>$$buffref</p>" ) if length $$buffref;
$req->print_stdout( "</body></html>" );
}
return 0;
},
},
stderr => {
on_read => sub {
my ( undef, $buffref, $closed ) = @_;
if( $$buffref =~ s{^(.*?)\n}{} ) {
$req->print_stderr( $1 );
return 1;
}
if( $closed ) {
# Deal with a final partial line the child may have written
$req->print_stderr( "$$buffref\n" ) if length $$buffref;
}
return 0;
},
},
on_finish => sub {
my ( undef, $exitcode ) = @_;
$req->finish( $exitcode );
},
);
if( !defined $kid ) {
$req->print_stdout(
"Content-type: text/plain\r\n" .
"\r\n" .
"Could not run $FORTUNE - $!\r\n"
);
$req->finish;
return;
}
# Print CGI header
$req->print_stdout(
"Content-type: text/html\r\n" .
"\r\n" .
"<html>" .
" <head><title>Fortune</title></head>" .
" <body><h1>$FORTUNE says:</h1>"
);
}
#!/usr/bin/perl -w
use strict;
use Net::Async::FastCGI;
use IO::Async::Loop;
my $loop = IO::Async::Loop->new();
sub on_request
{
my ( $fcgi, $req ) = @_;
my $env = $req->params();
my $path = $env->{PATH_INFO} || "/";
my $qs = $env->{QUERY_STRING};
my $method = $env->{REQUEST_METHOD} || "GET";
my $page = <<EOF;
<html>
<head>
<title>FCGI::Async testing page</title>
</head>
<body>
<h1>Path</h1><pre>$path</pre>
<h2>Query String</h2><pre>$qs</pre>
<h2>Method</h2><pre>$method</pre>
</body>
</html>
EOF
$req->print_stdout(
"Content-type: text/html\r\n" .
"Content-length: " . length( $page ) . "\r\n" .
"\r\n" .
$page . "\r\n"
);