CGI::MiniSvr(3)User Contributed Perl DocumentationCGI::MiniSvr(3)NAMECGI::MiniSvr - Adds to CGI::Base the ability for a CGI
script to become a mini http server.
SYNOPSIS
use CGI::MiniSvr;
$cgi = new CGI::MiniSvr;
$cgi = new CGI::MiniSvr $port_or_path;
$cgi = new CGI::MiniSvr $port_or_path, $timeout_mins;
$cgi->port; # return MiniSvr port number with leading colon
$cgi->spawn; # fork/detach from httpd
$cgi->get; # get input
$cgi->pass_thru($host, $port);
$cgi->redirect($url);
$cgi->done; # end 'page' and close connection (high-level)
$cgi->close; # just close connection (low-level)
See also the CGI::Base methods.
DESCRIPTION
This file implements the CGI::MiniSvr object. This object
represents an alternative interface between the
application and an HTTP deamon.
In a typical CGI scenario the interface is just a
collection of environment variables passed to a process
which then generated some outout and exits. The CGI::Base
class implements this standard interface.
The CGI::MiniSvr class inherits from CGI::Base and extends
it to implement a 'mini http daemon' which can be spawned
(forked) from a CGI script in order to maintain state
information for a client 'session'.
This is very useful. It neatly side-steps many of the
painful issues involved in writing real-world multi-screen
applications using the standard CGI interface (namely
saving and restoring state between screens).
Another use for the MiniSvr is to allow cgi scripts to
produce output pages with dynamically generated in-line
graphics (for example). To do this the script would spawn
a MiniSvr and refer to its port number in the URL's for
the embedded images. The MiniSvr would then sit on the
port, with a relatively short timeout, ready to serve the
requests for those images. Once all the images have been
24/Aug/1997 perl 5.005, patch 03 1
CGI::MiniSvr(3)User Contributed Perl DocumentationCGI::MiniSvr(3)
served the MiniSvr would simply exit.
Like the CGI::Base module the CGI::MiniSvr module does not
do any significant data parsing. Higher level query
processing (forms etc) is performed by the CGI::Request
module.
Note that the implementation of these modules means that
you should invoke new CGI::Base; before new CGI::MiniSvr;.
This is the natural order anyway and so should not be a
problem.
WARNING!
This module is not a good solution to many problems! It is
only a good solution to some. It should only be used by
those who understand why it is not a good solution to many
problems!
For those who don't see the pitfalls of the mini server
approach, consider just this one example: what happens to
your machine if new 'sessions' start, on average, faster
than abandoned ones timeout?
Security and short-lifespan URL's are some of the other
problems.
If in doubt don't use it! If you do then don't blame me
for any of the problems you may (will) experience. You
have been warned!
DIRECT ACCESS USAGE
In this mode the MiniSvr creates an internet domain socket
and returns to the client a page with URL's which contain
the MiniSvr's own port number.
$q = GetRequest(); # get initial request
$cgi = new CGI::MiniSvr;# were going to switch to CGI::MiniSvr later
$port = $cgi->port; # get our port number (as ':NNNN') for use in URL's
$me = "http://$SERVER_NAME$port$SCRIPT_NAME"; # build my url
print "Hello... <A HREF="$me?INSIDE"> Step Inside ...</A>\r\n";
$cgi->done(1); # flush out page, include debugging
$cgi->spawn and exit 0; # fork, original cgi process exits
CGI::Request::Interface($cgi); # default to new interface
while($q = GetQuery() or $cgi->exit){ # await request/timeout
...
}
24/Aug/1997 perl 5.005, patch 03 2
CGI::MiniSvr(3)User Contributed Perl DocumentationCGI::MiniSvr(3)
INDIRECT ACCESS USAGE
In this mode the MiniSvr creates a unix domain socket and
returns to the client a page with a hidden field
containing the path to the socket.
$q = GetRequest(); # get initial request
$path = $q->param('_minisvr_socket_path');
if ($path) {
# just pass request on to our mini server
$q->cgi->pass_thru('', $path) or (...handle timeout...)
$q->cgi->done;
} else {
# launch new mini server
$path = "/tmp/cgi.$$";
$cgi = new CGI::MiniSvr $path; # unix domain socket
# code here mostly same as 'DIRECT ACCESS' above except that
# the returned page has an embedded field _minisvr_socket_path
# set to $path
...
}
SUBCLASSING THE MINISVR
In some cases you may wish to have more control over the
behaviour of the mini-server, such as handling some
requests at a low level without disturbing the
application. Subclassing the server is generally a good
approach. Use something like this:
# Define a specialised subclass of the MiniSvr for this application
{
package CGI::MiniSvr::FOO;
use CGI::MiniSvr;
@ISA = qw(CGI::MiniSvr);
# Default behaviour for everything except GET requests for .(gif|html|jpg)
# Note that we must take great care not to: a) try to pass_thru to ourselves
# (it would hang), or b) pass_thru to the server a request which it will
# try to satisfy by starting another instance of this same script!
sub method_GET {
my $self = shift;
if ($self->{SCRIPT_NAME} =~ m/\.(gif|jpg|html)$/){
$self->pass_thru('', $self->{ORIG_SERVER_PORT});
$self->done;
return 'NEXT';
}
1;
}
# ... other overriding methods can be defined here ...
}
24/Aug/1997 perl 5.005, patch 03 3
CGI::MiniSvr(3)User Contributed Perl DocumentationCGI::MiniSvr(3)
Once defined you can use your new customised mini server
by changing:
$cgi = new CGI::MiniSvr;
into:
$cgi = new CGI::MiniSvr::FOO;
With the example code above any requests for gif, jpg or
html will be forwarded to the server which originally
invoked this script. The application no longer has to deal
with them. Note: this is just an example usage for the
mechanism, you would typically generate pages in which any
embedded images had URL's which refer explicitly to the
main httpd.
With a slight change in the code above you can arrange for
the handling of the pass-thru to occur in a subprocess.
This frees the main process to handle other requests.
Since the MiniSvr typically only exists for one process,
forking off a subprocess to handle a request is only
useful for browsers such as Netscape which make multiple
parallel requests for inline images.
if ($self->{SCRIPT_NAME} =~ m/\.(gif|html|jpg)$/){
if ($self->fork == 0) {
$self->pass_thru('', $self->{ORIG_SERVER_PORT});
$self->exit;
}
$self->done;
return 'NEXT';
}
Note that forking can be expensive. It might not be worth
doing for small images.
FEATURES
Object oriented and sub-classable.
Transparent low-level peer validation (no application
involvement but extensible through subclassing).
Transparent low-level pass_thru/redirecting of URL's the
application is not interested in (no application
involvement but extensible through subclassing).
Effective timeout mechanism with default and per-call
settings.
Good emulation of standard CGI interface (for code
portability).
24/Aug/1997 perl 5.005, patch 03 4
CGI::MiniSvr(3)User Contributed Perl DocumentationCGI::MiniSvr(3)
RECENT CHANGES
2.2 and 2.3
Slightly improved documentation. Added a basic fork()
method. Fixed timeout to throw an exception so it's
reliable on systems which restart system calls.
Socket/stdio/filehandle code improved. Cleaned up
done/close relationship. Added experimental support
for optionally handling requests by forking on a
case-by-case basis. This is handy for serving
multiple simultaneous image requests from Netscape
for example. Added notes about the MiniSvr, mainly
from discussions with Jack Shirazi Removed old
explicit port searching code from _new_inet_socket().
Improved SIGPIPE handling (see CGI::Base).
2.1 Fixed (worked around) a perl/stdio bug which affected
POST handling. Changed some uses of map to foreach.
Slightly improved debugging. Added support for any
letter case in HTTP headers. Enhanced test code.
2.0 Added more documentation and examples. The max
pending connections parameter for listen() can now be
specified as a parameter to new(). SIGPIPE now
ignored by default. Simplified inet socket code with
ideas from Jack Shirazi. Improved server Status-Line
header handling. Fixed validate_peer() error handling
and redirect(). Simplified get_vars() by splitting
into get_valid_connection() and read_headers(). Moved
example method_GET() out of MiniSvr and into the test
script.
The module file can be run as a cgi script to execute
a demo/test. You may need to chmod +x this file and
teach your httpd that it can execute *.pm files.
1.18 Added note about possible use of MiniSvr to serve
dynamically generated in-line images. Added optional
DoubleFork mechanism to spawn which might be helpful
for buggy httpd's, off by default.
1.17 Added support for an 'indirect, off-net, access' via
a local UNIX domain socket in the file system. Now
uses strict. ORIG_* values now stored within object
and not exported as globals (Base CGI vars remain
unchanged). See CGI::Base for some more details.
FUTURE DEVELOPMENTS
Full pod documentation.
None of this is perfect. All suggestions welcome.
24/Aug/1997 perl 5.005, patch 03 5
CGI::MiniSvr(3)User Contributed Perl DocumentationCGI::MiniSvr(3)
Test unix domain socket mechanism.
Issue/problem - the handling of headers. Who outputs them
and when? We have a sequence of: headers, body, end, read,
headers, body, end, read etc. The problem is that a random
piece of code can't tell if the headers have been output
yet. A good solution will probably have to wait till we
have better tools for writing HTML and we get away from
pages of print statements.
A method for setting PATH_INFO and PATH_TRANSLATED to
meaningful values would be handy.
AUTHOR, COPYRIGHT and ACKNOWLEDGEMENTS
This code is Copyright (C) Tim Bunce 1995. All rights
reserved. This program is free software; you can
redistribute it and/or modify it under the same terms as
Perl itself.
This module includes ideas from Pratap Pereira
<pereira@ee.eng.ohio-state.edu>, Jack Shirazi
<js@biu.icnet.uk> and others.
IN NO EVENT SHALL THE AUTHORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
DOCUMENTATION (INCLUDING, BUT NOT LIMITED TO, LOST
PROFITS) EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
SEE ALSO
CGI::Base, CGI::Request, URI::URL
SUPPORT
Please use comp.infosystems.www.* and comp.lang.perl.misc
for support. Please do _NOT_ contact the author directly.
I'm sorry but I just don't have the time.
a mini http server."
24/Aug/1997 perl 5.005, patch 03 6
CGI::MiniSvr(3)User Contributed Perl DocumentationCGI::MiniSvr(3)24/Aug/1997 perl 5.005, patch 03 7