Archive for December, 2007

I saw the light

Monday, December 24th, 2007

Upgrading my operating system to Leopard didn’t help my development environment at all because Leopard ships with Apache 2.0 without mod_perl and that’s a problem because mod_perl doesn’t compile properly. With all this I had to switch to lighttpd and run HTML::Mason with FCGI, for that I had to install the new web server and create a FCGI handler and configure lighttpd to run the pages trough this handler. This is how the handler looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#!/usr/bin/perl
 
use strict;
use warnings;
 
use CGI::Fast;
use HTML::Mason::CGIHandler;
use BSD::Resource;
use HTML::Entities;
 
my $handler;
while (my $cgi = CGI::Fast->new()) {
	$handler = HTML::Mason::CGIHandler->new(
	data_dir      => $ENV{MASON_DATA_ROOT}, 
	error_mode    => 'output', 
	allow_globals => [],
	request_class => 'MasonX::Request::WithApacheSession',
 
	session_cookie_name => 'sid',
	session_cookie_domain => '127.0.0.1',
	session_class => 'Apache::Session::File',
	session_directory => '/usr/mason/Tracker/sessions/data',
	session_lock_directory => '/usr/mason/Tracker/sessions/locks', 
	session_use_cookie => 1,
	session_cookie_expires => '+1d'
	) if(!$handler);
 
    my($url) = ($ENV{'REQUEST_URI'}=~/(.*)/);   
    $url =~ s{\?.*}{};
    eval {
	$url .= "/index.html" if (
		(!$handler->interp->comp_exists($url)) and 
		($handler->interp->comp_exists("${url}/index.html")));
 
        $handler->_handler({comp => $url, cgi => $cgi,});
    };
 
    if(my $raw_error = $@) {
	print $cgi->header();
	print "A really fatal error occured while processing your request:";
	print encode_entities( $raw_error );
    }
}
 
exit;

This example also contains the basic session configuration for the MasonX::Request::WithApacheSession and of course you need to change the paths. Also in order to work properly you need to read the previous article.

The next step is to configure lighttpd to use this handler, the configuration kinda looks something like this:

1
2
3
4
5
6
7
8
9
10
11
fastcgi.server = (
"/Tracker/app" => (
	(
	"socket" => "/tmp/fastcgi.socket",
	"bin-path" => "/Library/WebServer/CGI-Executables/mason.fcgi",
	"check-local" => "disable",
	"bin-environment" => (
	"MASON_COMP_ROOT" => "/Library/WebServer/Documents/Tracker/app",
	"MASON_DATA_ROOT" => "/usr/mason/Tracker"
	))
))

DON’T FORGET TO ENABLE mod_fastcgi in lighttpd. I used the same paths as Apache because I didn’t want to move the files and the links again plus I also have a lot of local scripts that are based on those paths. But you might still encounter some problems when you will try to restart the web server. On MacOS X you can configure launchd to take care of the automatic start/stop functions, but I’m on old fashion guy so .. I created a simple script for that:

1
2
3
4
5
#!/bin/bash
 
killall -9 lighttpd
rm -rf /tmp/fastcgi.socket-*
/usr/local/sbin/lighttpd -f /private/etc/lighttpd.conf

That should be sufficient to run lighttpd with Mason with MasonX::Request::WithApacheSession … so far I haven’t encountered any problems so please send me an email if you do. Merry Christmas everyone!

The court is now in SESSION! (uncensored version)

Friday, December 7th, 2007

Of course I got bored the past few days and I started working on some silly project just to have something to do. So I created my deploy environment on my hosting provider which is DreamHost, using FCGI and HTML::Mason … everything good so far until I had to use sessions in my application.

Said and done I installed from CPAN MasonX::Request::WithApacheSession from this point all my work really started to get ugly. MasonX::Request::WithApacheSession DOES NOT, AND I MEAN NOT WORK WITHOUT SOME PATCHING WITH FCGI (wtf?!?) it seems that there are several bugs (one in MasonX::Request::WithApacheSession and another two in Apache::Session::Wrapper).

So after several hours of googling the problem I managed to find a link that helped me solve some of the problems. Basically there were two patches one for MasonX::Request::WithApacheSession and one for the Apache::Session::Wrapper, after applying the patches the server stopped displaying “Internal Server Error” message which lead me to think that I was on the right track with the problem.

BUT when I tried to test it the browser was not receiving the cookie, that’s when I started to investigate the problem. I opened Apache::Session::Wrapper and looked in the “_bake_cookie” subroutine which is setting the cookie in browser and discovered that the $header_object variable is in fact an instance of HTML::Mason::FakeApache and the $meth variable called from that instance was called “err_headers_out”, this is how the cookie is set in browser, this is how my file looks (after applying the previous patches):

my $header_object = $self->{header_object};
 
for my $meth (@HeaderMethods)
{   
	if ( $header_object->can($meth) )
	{
		$header_object->$meth( 'Set-Cookie' => $cookie );
		last;
	}
}

The @HeaderMethods array contains to names err_headers_out and headers_out, HTML::Mason::FakeApache implements both those methods so obviously it was running the first one in the list which is err_headers_out the problem is that err_headers_out DOES NOT TAKE ANY MOTHER FUCKING PARAMETERS!!! but err_header_out (yes .. it’ without the “s”) does. The fix is pretty easy just remove the “s” and it should work.

Piss out !