Mod_perl2, apache2.2, and CGI::Ajax notes…

Following along in my mod_perl2 notes, I wanted to document how to get CGI::Ajax working with mod_perl2. I hit a couple of snags along the way that are worth noting. First, the generated javascript for my functions was calling httpd? + vars, rather than my URI /modperl_handler/ajax? + vars. This was frustrating, but I determined that it was grabbing httpd from $0, so I changed it locally and the script worked after that. The second snag I hit was because I was instantiating my CGImodule globally instead of locally, and I would get segfaults now and then. Instantiating it inside the handler was the right way to go. Here is a working example:

package AjaxTest;

use CGI;
use CGI::Ajax;

use Apache2::RequestRec();
use Apache2::RequestIO();
use Apache2::Const -compile => qw(OK);

sub handler {
    my ($r) = @_;

    my $cgi = new CGI;  # had this outside the handler and was getting segfaults

    # Have to redefine $0 for CGI::Ajax because it's used to call further URLs from
    # javascript ajax functions.  (otherwise it did "httpd?"...)
    local $0 = $ENV{"REQUEST_URI"};
    $0 =~ s/?.*//;

    # Start Ajax stuff
    my $pjx = new CGI::Ajax("test_ajax" => &test_ajax);
    # Don't compress javascript (1 for user fcns only, 2 for all)
    $pjx->JSDEBUG(1);
    # Send stderr to web logs
    $pjx->DEBUG(1);

    print $pjx->build_html( $cgi, &base_page);
    return Apache2::Const::OK;
}

sub base_page {
    return "Ajax mod_perl testmod_perl 2.0.2 on apache 2.2.2 rocks! <p><div id="test">Change me</div><p>nn";
}

sub test_ajax {
    my $time = time();
    return "Test successful; $time<p>";
}

1;

Mod_perl 2, apache 2.2, perl handler example

  1. Make sure that mod_perl.pm is being loaded on server start-up! In httpd.conf, have a line like:
    LoadModule perl_module modules/mod_perl.so
  2. The perl that runs with the apache server needs to know where you are putting your stuff, along with any other perl-isms at startup, so we set a perl file that gets sourced by apache/perl when loading. In httpd.conf, add:
    PerlRequire /path/to/your/perl_startup.pl

    This file itself, can set several things, but at a minimum adds the module path for your perl modules to be referenced in:

    use lib qw(/path/to/your/perl_modules);
    1;
  3. Now set up code for each specific handler! For each mod_perl app you put out there, you need to map a location to the perl module, in httpd.conf, like so:
    <Location /modperl_rocks>
           SetHandler perl-script
           PerlResponseHandler MyApache2::Rocks
    </Location>
  4. Next the perl code itself! In the perl lib directory defined above, /path/to/your/perl_modules, create a file MyApache2/Rocks.pmand have it look something like:
    package MyApache2::Rocks;
    
    use strict;
    use warnings;
    
    use Apache2::RequestRec();
    use Apache2::RequestIO();
    use Apache2::Const -compile => qw(OK);
    
    sub handler {
        my ($r) = @_;
        $r->content_type('text/html');
        print "mod_perl 2.0.2 on apache 2.2.2 rocks!n";
        return Apache2::Const::OK;
    }
    
    1;
  5. Finally, stop and restart apache, and for this example surf to /modperl_rocks. All should work well…

WebDAV

One of the up-and-coming web publishing tools is… not what you’d expect! Pretty much anything that can save a file to disk! Anything, that is, that can be extended to save a file with the WebDAV protocol. DAV stands for “Distributed Versioning and Authoring”. This particular topic will house my notes on getting WebDAV set up with my apache server, and getting clients to use it. Currently there’s a pretty extensive list of clients that support it, such as Microsoft Office and OpenOffice. See my notes on OpenOffice and others in the rest of the article…

Apache Setup
For Apache 2.2.0, these are the general settings that are needed/suggested for DAV functionality. (earlier versions of apache also support DAV, I just happen to be on 2.2.0 at the moment)

LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule dav_lock_module modules/mod_dav_lock.so
DavLockDB /usr/site/www/logs/DAVlock.db
BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully
BrowserMatch "MS FrontPage" redirect-carefully
BrowserMatch "^WebDrive" redirect-carefully
BrowserMatch "^WebDAVFS/1.[0123]" redirect-carefully
BrowserMatch "^gnome-vfs/1.0" redirect-carefully
BrowserMatch "^XML Spy" redirect-carefully
BrowserMatch "^Dreamweaver-WebDAV-SCM1" redirect-carefully

Take note with the DavLockDB line – you can’t just create that file and be done, because that file is not even used! It creates a .dir and a .pagfile with that prefix. Best to let apache own the directory the files are in, but you can probably pre-make and chown them…

Next, on a location-by-location basis, enble DAV:

Alias /davtest /usr/site/www/davtest/www
<Directory /usr/site/www/davtest/www>
    Dav on
    AuthType Digest
    AuthName DAV-upload
    AuthUserFile "/usr/site/apache-2.2.0/user.passwd"

    # Allow universal read-access, but writes are restricted to the admin user.
    <LimitExcept GET OPTIONS>
        require user admin
    </LimitExcept>
</Directory>

This is nice – authentication is required for DAV modification methods, but reading, such as is done by the webserver, requires no authentication.

OPEN OFFICE 2.0
The first thing you should do is change the options to use the Open/Save dialogs from OpenOffice instead of Windows (or Linux? I am not sure how they behave) because the Windows ones won’t let you save a new file to a DAV site. Open a blank document and go to Tools - Options - OpenOffice.org - General and check the “Use Openoffice.org dialogs” checkbox.
Now when you save a file (html, text, spreadsheet, etc), when you create the filename, simply enter the full path to the DAV file, such as http://mercury.guyton.net/davtest/testing.html. For saving a file, it’s the same thing, just enter the full path of the DAV site if the browser is not focused there already.

To load an existing file, it’s similar, and I believe works with either the openoffice or windows load dialogs. Better to stick with the openoffice ones though, so you can save new files.

One down side to OpenOffice was that it did not support digest authentication. We had to revert to Basic auth, which does not encrypt the password well. If it’s over SSL, that’s fine, but most users should be able to use HTTP and digest…

This still does not address images, though…. or other random file types.

NTLM

NTLM is the protocol that Internet Explorer uses to automatically log a user in to a site using the OS login credentials. There are lots of intranet applications that do this within an organization. What’s neat is that it’s not just limited to Internet Explorer and IIS.

First off, FireFox can do NTLM as well. In version 1.0, you need to navigate to about:config and find network.automatic-ntlm-auth.trusted-uris. Give it a value such as a domain (guyton.net) that you trust with your OS login credentials. Multiple hosts can be entered, sep. by commas. After that, automatic logins!

Note that to do this in IE, you need to go to Internet Options – Security – Local Intranet (or Trusted Sites) and add the host substring there (though it might need *.guyton.net or something similar).

OK, so enough about the browsers, what about the back-end servers? Since we like UNIX here, we aren’t gonna touch IIS. Apache 2 is our favorite way to go, and two methods exist:

So far I’ve experimented with the first one, and it seems to work OK. After half a day it seems that the website gets pretty slow in responding, so I suspect a memory leak.

I plan on trying the second one out tomorrow. It seems to support multiple domains and PDCs/BDCs for each, and returns the domain as well as the userid in the REMOTE_USER env var, which I need.

These should theoretically authenticate with samba as well, which can get data from an LDAP server. This is nice because the whole thing can be implemented with FireFox, Samba, Apache, and OpenLDAP, thus completely eliminating reliance on Microsoft products (other than OS login) while still providing single sign-on capabilities.

Apache compile standards

I’ve been spending time at work standardizing our Apache configuration and installs. It’s been fun working out exactly what modules we do/might need and compiling with the right performance enhancers (mpm=worker, enable nonportable atomics, etc).

I went ahead and upgraded the home server last night as well – got to a secure openssl and latest apache, and put a buncha modules as DSOs that I might include in the config later.

What a nice job – getting to work on Apache and open source stuff like that.