[cgiapp] cgiapp, cap::Dispatch, fastcgi,
and lighttpd -- a dummies guide.
George Hartzell
hartzell at alerce.com
Sun Sep 7 13:51:20 EDT 2008
Last week I spent a little more time than I care to disclose getting
something that I wrote for CGI::Application::Dispatch::Server running
under lighttpd using fastcgi. All of the necessary bits and hints are
scattered around and really anyone but a Dummy should be all set.
Since I managed to find a couple of sharp edges anyway, I thought it
might be worth gathering the info together here for posterity and/or
google.
I'm running everything from ports on FreeBSD-STABLE, but I don't think
that really matters for this.
* First things first. When you enable debugging in your lighttpd.conf
and find something like this:
2008-09-03 03:44:59: (mod_fastcgi.c.1033) child exited with
status 9 /home/hartzell/oligodb/fcgi/oligodb.fcgi
it probably means that whatever user lighttpd is running as is
unable to read your instance script (oligodb.fcgi above), not that
your instance script exited because of some problem it was having.
I think that lighttpd should be able to get enough info from
execvp/wait to tell the difference between being unable to start a
child and having it start then exit, but I haven't had a chance to
go bug hunting there yet.
* The next thing, you need to configure lighttpd to pass your requests
to your instance script via fastcgi. "Qiang at cgiapp from freenode"
added a section to
http://trac.lighttpd.net/trac/wiki/ApplicationsUsingLighttpd
that contains most of the necessary info. It helps to have the
url.rewrite stanza so that you can use url's like
"http://cgiapp/Home/home" and have them get passed via fastcgi to
your instance script (which let them match the way that I'd been
doing it under the standalone server).
This setup puts the instance script into the htdocs directory.
Other documentation for bin-path makes it clear that you can put the
script anywhere. If you *do* put it somewhere else, then you either
have to put a dummy file in the right place in your htdocs directory
or add
"check-local" => "disable"
in that same stanza. If you don't do one or other other you'll get
file not found errors, even though the file specified in bin-path is
there (#$@@$!!!). Not surprisingly, you should make sure that
whatever you specify for "socket" is readable/writeable by whatever
user lighttpd is running as.
* Next, you need to whip up a little instance script. Qiang's wiki
entry above gives the recipe for a standard CGI app and mentions
that it's easy for CGI::Application::Dispatch too. And it *is*
easy, once you get past the 'exited with status 9' problem described
above and the potential file-not-found problem. The only trick is
passing in a new CGI::Fast object for each query. For the record,
here's an instance script that works for me:
#!/usr/bin/perl
use warnings;
use strict;
#use lib qw(/usr/home/hartzell/oligodb/blib/lib);
use CGI::Fast();
use OligoDB::WebApp::Dispatch;
while (my $q = new CGI::Fast) {
OligoDB::WebApp::Dispatch->dispatch(args_to_new => {QUERY => $q});
}
* You can also do it with FCGI::Dispatch. Ron Savage posted a pointer
to great demo app that pretty much works right out of the box (watch
out for a couple of hard coded paths though), you can see his
message at:
http://www.mail-archive.com/cgiapp@lists.openlib.org/msg06532.html
I naively thought that all of the necessary magic was included in
his instance script, I transliterated it into my world and thought
that things were working. Actually, they only seemed to work but I
had params from older queries popping up in later ones (not
consistently, the bug depended on which of the pool of fastcgi
processes the request was passed to. It turns out that Ron was
whipping up a fresh CGI::Simple object using cgiapp_get_query() in
lib/CGI::Application/Test/Dispatch.pm. Everything worked swimmingly
with FCGI::Dispatch once I did something similar in my base class.
* For completeness' sake, Ron Savage also posted a description to the
list of how to "do it" using FCGI::ProcManager. I haven't tried it,
but I'm betting it works.... You can read it at:
http://www.mail-archive.com/cgiapp@lists.openlib.org/msg06730.html
So in summary, write an script that uses either CGI::Fast or
FCGI::Dispatch or FCGI::ProcManager that wraps your Dispatch class
and make sure that someone's generating a new query object for each
request, configure lighttp to pass those requests via fastcgi to the
script (watch for permission problems and either put the instance
script under the document root or set "check-local" appropriately),
and away you go.
g.
More information about the cgiapp
mailing list