MasonRecipe » History » Revision 14
« Previous |
Revision 14/20
(diff)
| Next »
EvanCarroll, 2007-08-26 00:37
= Using Mason with lighttpd (via FastCGI) =
Mason can be used with Lighttpd and is (arguably :-) easier to setup that Apache + mod_perl.
Here's my current setup. Requirements:
- Mason handles files ending with '/' or '.html' or '.css'.
- Other files statically served by lighttpd
- Load perl modules at fastcgi process start
- Disallow access to .mhtml files
First we need a mason handler, that lighttpd will use via FastCGI. I've called it mason_lighttpd_handler.fcgi. It does not need to be in any particular location.
{{{
#!perl
#!/usr/bin/perl
use CGI::Fast;
use HTML::Mason::CGIHandler;
use URI;
{
package HTML::Mason::Commands;
- anything you want available to components
use Storable qw(freeze thaw);
use HTTP::BrowserDetect;
- An example of how to keep a $dbh persistent
##our $dbh = DBI->connect_cached( - 'dbi:Pg:dbname=dbname'
- , 'username'
- , 'password'
- , {AutoCommit=>0, RaiseError=>1, PrintError=>1}
##) || die "Could not Connect to DB".$dbi::errstr ;
}
- lazily-instantiated variables
my $cgi;
my $h;
while ($cgi = new CGI::Fast()) { ## make sure it is alive! (if not it will reconnect) ## $HTML::Mason::Commands::dbh->ping;
my $uri = URI->new( $ENV{REQUEST_URI} );
- this is a hack, that emulates mod_perl behavior see notes at bottom
- You might not want this hack, and it might be worse than not having it
$uri->path( $uri->path . 'index.html' )
if $uri->path =~ /\/$/
;
$ENV{PATH_INFO} = $uri->path;
$ENV{QUERY_STRING} = $uri->query;
$ENV{REQUEST_URI} = "$uri";
- this is lazily instantiated because %ENV is not set at startup time
if (! $h) {
$h = HTML::Mason::CGIHandler->new(
comp_root => $ENV{MASON_COMP_ROOT}
, data_dir => $ENV{MASON_DATA_ROOT}
, error_mode => 'fatal'
, error_format => 'line' ## Three good globals dbh user and session
, allow_globals => [qw/$dbh $U $S/]
);
}
- hand off to mason
#eval { $h->handle_request };
eval { $h->handle_cgi_object($cgi) };
if ( my $raw_error = $@ ) {
$HTML::Mason::Commands::dbh->rollback; ## roll back
warn $raw_error; # print out a pretty system error page and log $raw_error
}- things went well
else {
$HTML::Mason::Commands::dbh->commit;
}
- things went well
}
exit 0;
}}}
Next we need to tell Lighttpd to process requests for this site and process them via this script and FastCGI. Here is the relevant fragment. I'm using a regexp for the hostname expression
but you may need something less complicated - see the Lighttpd docs for more information:
{{{
#!python
$HTTP["host"] =~ "hostnameexpression" {
server.document-root = "/path/to/your/document/root"
## map .css and '/' to .html so they will be handled by FastCGI
fastcgi.map-extensions = ( ".css" => ".html", "/" => ".html" )
index-file.names = ( "index.html" )
url.access-deny = ( ".mhtml" ) ## add autohandler/dhandler if you'd like
fastcgi.server = ( ".html" =>
((
"socket" => "/tmp/fastcgi.socket",
"bin-path" => "/path/to/the/mason_lighttpd_handler.fcgi",
"check-local" => "disable"
))
)
bin-environment = (
MASON_COMP_ROOT => '/your/comp/root',
MASON_DATA_ROOT => '/your/data/root'
)
}
}}}
That's it!
When you start lighttpd it will start several copies of your mason handler script, passing requests to them as appropriate.
One nice side-effect of this is that if you change a perl module (not a mason component) that would require you to restart/reload an apache mod_perl server, in this case you can just kill the perl fastcgi processes - lighttpd will notice and restart them, of course with your new module code in place.
Add debugging (via 'warn') to your handler script if you are getting unexpected results, you can see the output from it in the lighttpd eror log.
= Known issues =
$m->abort does not work correctly, see this page for details on why:
http://www.masonhq.com/docs/manual/1.28/CGIHandler.html#calling_abort___under_cgihandler
It looks like this is something that has to be fixed in Mason.
Migration from Apache/mod_* (mod_perl)First a prequil, mod_* (lang) embeeds the .so for the language in Apache. In doing so it knows things that Fastcgi doesn't, and can do things Fastcgi can't. Some of this behaviors users might be utilizing without knowing, here is a prime example:
In Apache, (mod_* not fastcgi) a request to '/' would be processed by:BR
- first looking for the DirectoryIndex (apache would do this.)BR
- call the wrapper with the found DirectoryIndex; or, call the wrapper, (which would call a dhandler) on the unfound file.
In Lighttpd, or just cgi in general, the resolution to the index-file is missing, so the wrapper will either be called on the requested file or not. See the "check-local" directive in lighttpd. In cgi, the index-file (Apache's DirectoryIndex) has no influence. For comparison Lighttpd/fastcgi looks like this:BR
- call the wrapper with the found file; or, call the wrapper with the un-found file dependent on check-local being disabled.BR
One horrible solution to this is to redirect all directories to the directory's index.html. A less-horrible solution would be to write the translation process in the wrapper (this only works if check-local is disabled).
Another problem -- expanding on the previously mentioned problem is an address with no path, just a query string. ie:
http://foo.com/?test.html or /?test.html, or /bar/?test.html
In Apache, the resolution looks like this:BR
- first looking for the DirectoryIndex (Apache would do this.)BR
- calling the wrapper with the found DirectoryIndex; with the query.BR
In Lighttpd, (i.e. cgi) this isn't so. Bottom line: index-files don't matter if you're sending everything to the wrapper (not checking for files existence.) If you app makes use of Apache's resolution this can sting. If you don't send everything to the wrapper, you'll completely lose the dhandler functionality.
= Credits =
Lateset rewrite (Evan Carroll <me@evancarroll.com>)
- added env variables for comp/data root
- added example of DBI persistence with fastcgi
- removed original query-parsing regex, used URI instead.
- added some globals to be shared
(Justin Hawkins <justin@hawkins.id.au>) First Draft.
This is very much in the category of "seems to work" at this stage. (initial note still applies)
Updated by EvanCarroll over 17 years ago · 14 revisions