Document Home

Previous- Moving Onto Some New Turf - Mod_Perl

Samples for this section


Installing and Configuring Mod_Perl To Run CGI Scripts Under Apache::Registry



As I said in the previous section, the basic installation of mod_perl on a debian machine is very simple. Just type "apt-get install apache-perl". That will take care of assuring that an apache binary with the embedded perl interpreter will be installed, along with the requisite support files. In general, the names of files and their locations follow the convention used by a vanilla debian apache installation, differing only in that the apache files and locations are labelled apache while the mod_perl counterparts are prefaced with apache-perl. Thus the configuration files for mod_perl are located in the directory /etc/apache-perl and the server control utility is apache-perl-ctl. By default, no httpd.conf file will be installed in the /etc/apache-perl directory, but a sample configuration file is included in the /usr/share/doc/apache-perl/examples subdirectory.


I am going to start this off by "morphing" the application I have now into the mod_perl environment. (In case you are not familiar with the term, "morphing" originated in the computer graphics field and refers to the process of applying a series of small transformations to one image, gradually turning it into another completely different image. You have seen examples of the output from this process on television and in the movies, though you may not have known what it was called.) To start this process, copy the httpd.conf file from the /etc/apache directory to /etc/apache-perl ("cp /etc/apache/httpd.conf /etc/apache-perl"). Now stop the running apache server by issuing the command "apachectl stop". (Occassionally you can run into a problem with an apache server that has been running for some time developing orphaned processes ... you will try to stop the server only to receive a response indicating that no servers are running, but if you type "ps -ax" you will see several "httpd" processes running. This means that there has been a glitch in the tracking of running apache processes. You can resolve this by killing each of those running processes by typing "kill xxx", where "xxx" is the numeric process ID in the list produced by "ps -ax", but I generally prefer to refresh the entire server environment by issuing "shutdown -r now". You can do thart if you are the only one working on the server, but check with your compatriots if others are involved. That kind of thing can lead to hard feelings <grin>. Once you have logged in again you should be able to stop the apache server without problems.) Once the apache server has been stopped, you can start the mod_perl-enabled server by issuing "apache-perl-ctl start". As long as you have an appropriate httpd.conf file in the /etrc/apache-perl directory the server should start. If it does not, examine whatever error messages you have received and check the /var/log/apache-perl/error.log file. As long as you have a working apache server previously, the httpd.conf file from that server should also work for mod_perl.


OK, so the server is running. If you execute the full cgi script (you should still have full_6.cgi, or something like it, in /usr/lib/cgi-bin from the last example), you will see that it runs, just as it did before. Just as it did before, no faster, no differently. If you sit back and thing about it for a minute (go ahead, it's okay), this makes perfect sense. The operation of the apache server is controlled by the httpd.conf file, and as long as that file is same one that I used to set up the vanilla apache server, the mod_perl enabled server is going to behave in exactly the same fashion regardless of the fact that it has incorporated the embedded perl interpreter.


This illustrates something about apache that is going to become an important theme in what is to come ... a substantial part of creating an application incorporating apache lies in an appropriate configuration of the httpd.conf file, telling apache how it is to handle things. One way to think about this is that in out current environment, when I call the cgi script, apache starts perl and gives it all of the information sent to it. The script reads that information, tells apache what to send back, and exits. When the browser responds to what has been sent back the whole process begins again. Developing more responsive applications using the apache server involves telling the server itself how to deal with certain kinds of requests, and embedding into the server the logic that will handle those requests. Clearly, then, I have to start working over the httpd.conf for the ralphzilla server.


Generally, the httpd.conf file specifies global configuration options, such as the default local userid under which web users interact with the local machine, near the beginning of the file, with items relating to specific circumstances afterward. While it is possible to configure the server to associate a set of actions for certain types of files on a server-wide basis (a file handler), the "heavy lifting" in the configuration of apache servers is generally done on a location level. In other words, in the httpd.conf you tell the server that any time there is a request for something in a given location it should be handled in a certain manner. My current task is to set up a configuration that will let the cgi script just as it currently exists run under the embedded perl interpreter in the mod_perl apache server. Therefore, I will set up a location to house scripts to be run in that fashion.


The location for which I am going to specify a handler can be either an actual directory location or a virtual location as defined in an alias line in the httpd.conf. This example closely conforms to the sample for mod_perl near the end of the httpd.conf installed in the /usr/share/doc/apache-perl/examples directory. Uncommented, with the conditional brackets that checked for mod_perl removed, that little section is as follows:


Alias /perl/ /var/www/perl/

<Location /perl>
  SetHandler perl-script
  PerlHandler Apache::Registry
  Options +ExecCGI
</Location>

First, as you can see, the alias line assigns the virtual directory /perl to the actual directory /var/www/perl. (This simply conforms to the apache convention of putting subdirectories under the document root, in this case the default /var/www. It is, of course, a good idea to maintain a coherent directory structure, but by no means must it conform to this specific convention.) Following the alias desclaration, the statements within the <location></location> tags define how requests for files within that directory should be handled. The first line, SetHandler, tells apache to treat those items as perl to be handled by the embedded interpreter. In the second line, PerlHandler, I tell mod_perl what code it should use to handle the request. In this instance, of course, it is the Apache::Registry module, which creates the environment that handles unmodified CGI scripts under mod_perl. The final line here adds ExecCGI to the options for this location. This is what tells apache to allow the execution of CGI scripts residing in this location. In the absence of this statement you would receive a "Permission Denied" error when trying to call a script located in the directory.


Now that the location has been configured you might think that I am ready to roll, but that is not the case. As the perl interpreter is, in effect, being loaded at apache startup, the shebang line
#!/usr/bin/perl -T
beginning the script is superflous. This might not seem like a big deal, but throwing the -T switch is how I turned on taint mode. Beyond being good programming practice for browser applications, taint mode is absolutely required for the use of the FileHandle::Deluxe module ... you may have noticed previously that if FileHandle::Deluxe is used and taint mode is not turned on, the script will bomb out. While it would be relatively easy to change to a straight filehandle where the FileHandle::Deluxe object is being used, that would be a backward approach to the problem. What I really want to do is turn on taint mode. Logically enough, this is also controlled in the httpd.conf file, and is a global setting. Simply place the statement
 PerlTaintCheck On
somewhere where it will be read as a global setting and the interpreter will be started as if the -T switch were thrown. (Any statement not within a special configuration section such as <location></location> sections is treated as a global option, although by convention global settings are set near the beginning of the file. If, on one hand, you put this in the wrong place the server will not start, and if you don't put it in the script will not run, so sooner or later you are bound to have it in the right spot <grin>).


Once these changes have been made, re-start apache and copy full.pl from the samples file for this section into the /var/www/perl directory, making sure that it is flagged as readable and executable by the userid as whom browser users are represented on the local machine. Access the script by typing "<servername>/perl/full.pl" into the address window of your browser, and you will see that it works just as it always did. Ah, but I can hear you now - "Where's the speed increase?". Well, enter another set. See? Much more rapid. And it will be that way for any user who hits the script from any machine until the server is re-started. The first time through the script has to be compiled, including the modules as they are called. After that, since the interpreter is still loaded with the httpd server and has the compiled script loaded, the server responds much more quickly.


However, as the interpreter and script stay loaded between requests from the client, the environment under which the script is executing is not freshly created each time it is called. As a result, global variables used indiscriminately in such scripts can behave unpredictably. In effect, when you access the script, you could be picking up a value in one of these variables set by another user. This can be avoided by using good coding practices, like scoping variables, which you can force yourself to adopt by calling the strict pragma ("use strict"). You may recall my discussion on the desirability of explicitly passing values to subroutines in the sections on module construction. I had this in mind at that time. As a result of those precautions, I have not to this point seen any such problems with this script. <knock on wood>


In the next section I will start calling the application with a custom handler, and in so doing will adopt some techniques that will further enhance its responsiveness.



Next - A Basic Perl Handler