Table of Contents:
The next step after building and installing your new mod_perl enabled
apache server, is to configure the server. To learn how to modify apache's
configuration files, please refer to the documentation included with the
apache distribution, or just view the files in
conf
directory and follow the instructions in these files - the embedded
comments within the file do a good job of explaining the options.
Before you start with mod_perl specific configuration, first configure apache, and see that it works. When done, return here to continue...
[ Note that prior to version 1.3.4, the default apache install used three configuration files -- httpd.conf, srm.conf, and access.conf. The 1.3.4 version began distributing the configuration directives in a single file -- httpd.conf. The remainder of this chapter refers to the location of the configuration directives using their historical location. ]
First, you need to specify the locations on a file-system for the scripts to be found.
Add the following configuration directives:
# for plain cgi-bin: ScriptAlias /cgi-bin/ /usr/local/myproject/cgi/ # for Apache::Registry mode Alias /perl/ /usr/local/myproject/cgi/ # Apache::PerlRun mode Alias /cgi-perl/ /usr/local/myproject/cgi/
Alias
provides a mapping of URL to file system object under
mod_perl
. ScriptAlias
is being used for mod_cgi
.
Alias defines the start of the URL path to the script you are referencing.
For example, using the above configuration, fetching
http://www.nowhere.com/perl/test.pl
, will cause the server to look for the file test.pl
at /usr/local/myproject/cgi
, and execute it as an Apache::Registry
script if we define Apache::Registry
to be the handler of /perl
location (see below). The URL
http://www.nowhere.com/perl/test.pl
will be mapped to
/usr/local/myproject/cgi/test.pl
. This means that you can have all your CGIs located at the same place in
the file-system, and call the script in any of three modes simply by
changing the directory name component of the URL (cgi-bin|perl|cgi-perl
) - is not this neat? (That is the configuration you see above - all three
Aliases point to the same directory within your file system, but of course
they can be different). If your script does not seem to be working while
running under mod_perl, you can easily call the script in straight mod_cgi
mode without making any script changes (in most cases), but rather by
changing the URL you invoke it by.
FYI: for modperl ScriptAlias
is the same thing as:
Alias /foo/ /path/to/foo/ SetHandler cgi-handler
where SetHandler cgi-handler
invokes mod_cgi. The latter will be overwritten if you enable Apache::Registry
. In other words,
ScriptAlias
does not work for mod_perl, it only appears to work when the additional
configuration is in there. If the
Apache::Registry
configuration came before the ScriptAlias
, scripts would be run under mod_cgi. While handy, ScriptAlias
is a known kludge, always better to use Alias
and SetHandler
.
Of course you can choose any other Alias (you will use it later in
httpd.conf
), you can choose to use all three modes or only one of these. It is
undesirable to run scripts in plain mod_cgi from a mod_perl-enabled server
- the price is too high, it is better to run these on plain apache server.
(See Standalone mod_perl Enabled Apache Server)
Now we will work with the httpd.conf
file. I add all the mod_perl stuff at the end of the file, after the native
apache configurations.
First we add:
<Location /perl> #AllowOverride None SetHandler perl-script PerlHandler Apache::Registry Options ExecCGI allow from all PerlSendHeader On </Location>
This configuration causes all scripts that are called with a /perl
path prefix to be executed under the Apache::Registry
module and as a CGI (so the ExecCGI, if you omit this option the script will be printed to the caller's
browser as a plain text or possibly will trigger a 'Save-As' window).
PerlSendHeader On
tells the server to send an HTTP header to the browser on every script
invocation. You will want to turn this off for nph (non-parsed-headers)
scripts. PerlSendHeader On
means to call
ap_send_http_header()
after parsing your script headers. It is only meant for CGI emulation, its
always better to use CGI->header
from CGI.pm
module or $r->send_http_header
directly.
Remember the Alias from the section above? We must use the same
Alias
here, if you use Location
that does not have the same
Alias
defined in srm.conf
, the server will fail to locate the script in the file system. (We are
talking about script execution here -- there are cases where Location
is something that is being executed by the server itself, without having
the corresponding file, like /perl-status
location.)
Note that sometimes you will have to add :
PerlModule Apache::Registry
before you specify the location that uses Apache::Registry
as a
PerlHandler
. Basically you can start running the scripts in the
Apache::Registry
mode...
You have nothing to do about /cgi-bin
location (mod_cgi), since it has nothing to do with mod_perl.
Here is a similar location configuration for Apache::PerlRun
(More about Apache::PerlRun):
<Location /cgi-perl> #AllowOverride None SetHandler perl-script PerlHandler Apache::PerlRun Options ExecCGI allow from all PerlSendHeader On </Location>
You may load modules from the config file at server startup via:
PerlModule Apache::DBI CGI DBD::Mysql
There is a limit of 10 PerlModule
's, if you need more to be loaded when the server starts, use one PerlModule
to pull in many or write them all in a regular perl syntax and put them
into a startup file which can be loaded with use of the PerlRequire
directive.
PerlRequire /home/httpd/perl/lib/startup.pl
Both PerlModule
and PerlRequire
are implemented by require(),
but there is a subtle change. PerlModule
works like use(),
expecting a module name without .pm
extension and slashes.
Apache::DBI
is OK, while Apache/DBI.pm
is not. PerlRequire
is the opposite to PerlModule
-- it expects a relative or full path to the module or a filename, like in
the example above.
As with any file that's being required()
-- it must return a true
value, to ensure that this happens don't forget to add 1;
at the end of such files.
We must stress that all the code that is run at the server initialization
time is run with root priveleges if you are executing it as a root user
(you have to unless you choose an unpriveledged port, above 1024.
somethings that you might have to if you don't have a root access. Just
remember that you better pick a well known port like 8000 or 8080 since
other non-standard ports might be blocked by firewalls that protect many
organizations and individuals). This means that anyone who has write access
to a script or module that is loaded by PerlModule
or PerlRequire
, effectively has root access to the system. You might want to take a look
at the new and experimental PerlOpmask
directive and PERL_OPMASK_DEFAULT
compile time option to try to disable some dangerous operators.
As you know Apache specifies about 11 phases of the request loop, namely in that order: Post-Read-Request, URI Translation, Header Parsing, Access Control, Authentication, Authorization, MIME type checking, FixUp, Response (Content phase). Logging and finally Cleanup. These are the stages of a request where the Apache API allows a module to step in and do something. There is a dedicated PerlHandler for each of these stages. Namely:
PerlChildInitHandler PerlPostReadRequestHandler PerlInitHandler PerlTransHandler PerlHeaderParserHandler PerlAccessHandler PerlAuthenHandler PerlAuthzHandler PerlTypeHandler PerlFixupHandler PerlHandler PerlLogHandler PerlCleanupHandler PerlChildExitHandler
The first 4 handlers cannot be used in the <Location
>,
<Directory
>, <Files
> and .htaccess
file, the main reason is all the above require a known path to the file in
order to bind a requested path with one or more of the identifiers above.
Starting from PerlHeaderParserHandler
(5th) URI is allready being mapped to a physical pathname, thus can be used
to match the <Location
>,
<Directory
> or <Files
> configuration section, or to look at
.htaccess
file if exists at the specified directory in the translated path.
The Apache documentation (or even better -- the ``Writing Apache Modules with Perl and C'' book by Doug MacEachern and Lincoln Stein) will tell you all about those stages and what your modules can do. By default, these hooks are disabled at compile time, see the INSTALL document for information on enabling these hooks.
Note that by default Perl API expects a subrotine called handler
to handle the request in the registered PerlHandler module. Thus if your
module implements this subrotine, you can register the handler as simple as
writing:
Perl*Handler Apache::SomeModule
replace Perl*Handler with a wanted name of the handler. mod_perl will preload the specified
module for you. But if you decide to give the handler code a different
name, like my_handler
, you must preload the module and to write explicitly the chosen name.
PerlModule Apache::SomeModule Perl*Handler Apache::SomeModule::my_handler
Please note that the former approach will not preload the module at the
startup, so either explicitly preload it with PerlModule
directive, add it to the startup file or use a nice shortcut the
Perl*Handler
syntax suggests:
Perl*Handler +Apache::SomeModule
Notice the leading +
character. It's equal to:
PerlModule Apache::SomeModule Perl*Handler Apache::SomeModule
If a module wishes to know what handler is currently being run, it can find out with the current_callback method. This method is most useful to PerlDispatchHandlers who wish to only take action for certain phases.
if($r->current_callback eq "PerlLogHandler") { $r->warn("Logging request"); }
With the mod_perl stacked handlers mechanism, it is possible for more than
one Perl*Handler
to be defined and run during each stage of a request.
Perl*Handler directives can define any number of subroutines, e.g. (in config files)
PerlTransHandler OneTrans TwoTrans RedTrans BlueTrans
With the method, Apache->push_handlers()
, callbacks can be added to the stack by scripts at runtime by mod_perl
scripts.
Apache->push_handlers()
takes the callback hook name as its first argument and a subroutine name or
reference as its second. e.g.:
Apache->push_handlers("PerlLogHandler", \&first_one); $r->push_handlers("PerlLogHandler", sub { print STDERR "__ANON__ called\n"; return 0; });
After each request, this stack is cleared out.
All handlers will be called unless a handler returns a status other than OK
or DECLINED
.
example uses:
CGI.pm
maintains a global object for its plain function interface. Since the
object is global, it does not go out of scope, DESTROY is never called. CGI->new
can call:
Apache->push_handlers("PerlCleanupHandler", \&CGI::_reset_globals);
This function will be called during the final stage of a request,
refreshing CGI.pm
's globals before the next request comes in.
Apache::DCELogin
establishes a DCE login context which must exist for the lifetime of a
request, so the DCE::Login
object is stored in a global variable. Without stacked handlers, users must
set
PerlCleanupHandler Apache::DCELogin::purge
in the configuration files to destroy the context. This is not
``user-friendly''. Now, Apache::DCELogin::handler
can call:
Apache->push_handlers("PerlCleanupHandler", \&purge);
Persistent database connection modules such as Apache::DBI
could push a PerlCleanupHandler
handler that iterates over %Connected
, refreshing connections or just checking that ones have not gone stale.
Remember, by the time we get to PerlCleanupHandler
, the client has what it wants and has gone away, we can spend as much time
as we want here without slowing down response time to the client (but the
process is unavailable for serving new request befor the operation is
completed).
PerlTransHandlers
may decide, based on URI or other condition, whether or not to handle a
request, e.g. Apache::MsqlProxy
. Without stacked handlers, users must configure:
PerlTransHandler Apache::MsqlProxy::translate PerlHandler Apache::MsqlProxy
PerlHandler
is never actually invoked unless translate()
sees the request is a proxy request ($r->proxyreq
), if it is a proxy request, translate()
sets $r->handler("perl-script")
, only then will PerlHandler
handle the request. Now, users do not have to specify PerlHandler Apache::MsqlProxy
, the translate()
function can set it with push_handlers()
.
Includes, footers, headers, etc., piecing together a document, imagine (no need for SSI parsing!):
PerlHandler My::Header Some::Body A::Footer
A little test:
#My.pm package My;
sub header { my $r = shift; $r->content_type("text/plain"); $r->send_http_header; $r->print("header text\n"); } sub body { shift->print("body text\n") } sub footer { shift->print("footer text\n") } 1; __END__
#in config <Location /foo> SetHandler "perl-script" PerlHandler My::header My::body My::footer </Location>
Parsing the output of another PerlHandler? this is a little more tricky, but consider:
<Location /foo> SetHandler "perl-script" PerlHandler OutputParser SomeApp </Location> <Location /bar> SetHandler "perl-script" PerlHandler OutputParser AnotherApp </Location>
Now, OutputParser goes first, but it untie()'s
*STDOUT
and re-tie()'s to its own package like so:
package OutputParser;
sub handler { my $r = shift; untie *STDOUT; tie *STDOUT => 'OutputParser', $r; } sub TIEHANDLE { my($class, $r) = @_; bless { r => $r}, $class; } sub PRINT { my $self = shift; for (@_) { #do whatever you want to $_ $self->{r}->print($_ . "[insert stuff]"); } }
1; __END__
To build in this feature, configure with:
% perl Makefile.PL PERL_STACKED_HANDLERS=1 [PERL_FOO_HOOK=1,etc]
Another method Apache->can_stack_handlers
will return TRUE if mod_perl was configured with PERL_STACKED_HANDLERS=1
, FALSE otherwise.
If a Perl*Handler is prototyped with $$
, this handler will be invoked as method. e.g.
package My; @ISA = qw(BaseClass); sub handler ($$) { my($class, $r) = @_; ...; } package BaseClass; sub method ($$) { my($class, $r) = @_; ...; } __END__
Configuration:
PerlHandler My
or
PerlHandler My->handler
Since the handler is invoked as a method, it may inherit from other classes:
PerlHandler My->method
In this case, the My
class inherits this method from BaseClass
.
To build in this feature, configure with:
% perl Makefile.PL PERL_METHOD_HANDLERS=1 [PERL_FOO_HOOK=1,etc]
To reload PerlRequire
, PerlModule
, other use()
'd modules and flush the Apache::Registry
cache on server restart, add:
PerlFreshRestart On Make sure you read L<Evil things might happen when using PerlFreshRestart|warnings/Evil_things_might_happen_when_us>.
A very useful feature. You can watch what happens to the perl guts of the server. Below you will find the instructions of configuration and usage of this feature
Add this to httpd.conf
:
<Location /perl-status> SetHandler perl-script PerlHandler Apache::Status order deny,allow #deny from all #allow from </Location>
If you are going to use Apache::Status
, it's important to put it as a first module in the start-up file, or in
the httpd.conf
(after
Apache::Registry
):
# startup.pl use Apache::Registry (); use Apache::Status (); use Apache::DBI ();
If you don't put Apache::Status
before Apache::DBI
then you don't get Apache::DBI
's menu entry in status.
Assuming that your mod_perl server listens to port 81, fetch http://www.nowhere.com:81/perl-status
Embedded Perl version 5.00502 for Apache/1.3.2 (Unix) mod_perl/1.16 process 187138, running since Thu Nov 19 09:50:33 1998
This is the linked menu that you should see:
Signal Handlers Enabled mod_perl Hooks PerlRequire'd Files Environment Perl Section Configuration Loaded Modules Perl Configuration ISA Tree Inheritance Tree Compiled Registry Scripts Symbol Table Dump
Let's follow for example : PerlRequire'd Files -- we see:
PerlRequire Location /usr/myproject/lib/apache-startup.pl /usr/myproject/lib/apache-startup.pl
From some menus you can continue deeper to peek at the perl internals of the server, to watch the values of the global variables in the packages, to the list of cached scripts and modules and much more. Just click around...
Sometimes when you fetch /perl-status
you and follow the Compiled
Registry Scripts link from the status menu -- you see no listing of scripts at all. This is
absolutely correct -- Apache::Status
shows the registry scripts compiled in the httpd child which is serving
your request for /perl-status
. If a child has not compiled yet the script you are asking for, /perl-status
will just show you the main menu. This usually happens when the child was
just spawned.
PerlSetEnv key val PerlPassEnv key
PerlPassEnv
passes, PerlSetEnv
sets and passes the
ENVironment variables to your scripts. you can access them in your scripts through %ENV
(e.g. $ENV{"key"}
).
Regarding the setting of PerlPassEnv PERL5LIB
in httpd.conf If you turn on taint checks (PerlTaintMode On
), $ENV{PERL5LIB}
will be ignored (unset).
PerlSetVar
is very similar to PerlSetEnv
, but you extract it with another method. In <Perl> sections:
push @{ $Location{"/"}->{PerlSetVar} }, [ 'FOO' => BAR ];
and in the code you read it with:
my $r = Apache->request; print $r->dir_config('FOO');
Since many times you have to add many perl directives to the configuration
file, it can be a good idea to put all of these into a one file, so the
configuration file will be cleaner. Add the following line to httpd.conf
:
# startup.perl loads all functions that we want to use within # mod_perl Perlrequire /path/to/startup.pl
before the rest of the mod_perl configuration directives.
Also you can call perl -c perl-startup
to test the file's syntax. What does this take?
An example of perl-startup file:
use strict; # extend @INC if needed use lib qw(/dir/foo /dir/bar); # make sure we are in a sane environment. $ENV{GATEWAY_INTERFACE} =~ /^CGI-Perl/ or die "GATEWAY_INTERFACE not Perl!"; # for things in the "/perl" URL use Apache::Registry; #load perl modules of your choice here #this code is interpreted *once* when the server starts use LWP::UserAgent (); use DBI (); # tell me more about warnings use Carp (); $SIG{__WARN__} = \&Carp::cluck; # Load CGI.pm and call its compile() method to precompile # (but not to import) its autoloaded methods. use CGI (); CGI->compile(':all');
Note that starting with $CGI::VERSION
2.46, the recommended method to precompile the code in CGI.pm
is:
use CGI qw(-compile :all);
But the old method is still available for backward compatibility.
See also Apache::Status
Modules that are being loaded at the server startup will be shared among
server children, so only one copy of each module will be loaded, thus
saving a lot of RAM for you. Usually I put most of the code I develop into
modules and preload them from here. You can even preload your CGI script
with Apache::RegistryLoader
and preopen the DB connections with Apache::DBI
. (See Preload Perl modules at server startup).
Many people wonder, why there is a need for duplication of use()
clause both in startup file and in the script itself. The question rises
from misunderstanding of the use()
operand. use()
consists of two other operands, namely require()
and import()
. So when you write:
use Foo qw(bar);
perl actually does:
require Foo.pm; import qw(bar);
When you write:
use Foo qw();
perl actually does:
require Foo.pm; import qw();
which means that the caller does not want any symbols to be imported. Why
is this important? Since some modules has @EXPORT
set to a list of tags to be exported by default and when you write:
use Foo;
and think nothing is being imported, the import()
call is being executed and probably some symbols do being imported. See the
docs/source of the module in question to make sure you use()
it correctly. When you write your own modules, always remember that it's
better to use @EXPORT_OK
instead of @EXPORT
, since the former doesn't export tags unless it was asked to.
Since the symbols that you might import into a startup's script namespace
will be visible by none of the children, scripts that need a
Foo
's module exported tags have to pull it in like if you did not preload Foo
at the startup file. For example, just because you have
use()d
Apache::Constants
in the startup script, does not mean you can have the following handler:
package MyModule; sub { my $r = shift; ## Cool stuff goes here return OK; }
1;
You would either need to add:
use Apache::Constants qw( OK );
Or instead of return OK;
say:
return Apache::Constants::OK;
See the manpage/perldoc on Exporter
and perlmod
for more on
import()
.
PerlRequire
allows you to execute code that preloads modules and does more things.
Imported or defined variables are visible in the scope of the startup file.
It is a wrong assumption that global variables that were defined in the
startup file, will be accessible by child processes.
You do have to define/import variables in your scripts and they will be
visible inside a child process who run this script. They will be not shared
between siblings. Remember that every script is running in a specially
(uniquely) named package - so it cannot access variables from other
packages unless it inherits from them or use()
's them.
apachectl configtest
tests the configuration file without starting the server. You can safely
modify the configuration file on your production server, if you run this
test before you restart the server. Of course it is not 100% error prone,
but it will reveal any syntax errors you might do while editing the file.
'apachectl configtest
' is the same as 'httpd -t
' and it actually executes the code in startup.pl, not just parses it. <Perl
> configuration has always started Perl during the configuration read,
Perl{Require,Module}
do so as well.
If you want your startup code to get a control over the -t
(configtest
) server launch, start the server configuration test with:
httpd -t -Dsyntax_check
and in your startup file, add (at the top):
return if Apache->define('syntax_check');
if you want to prevent the code in the file from being executed.
For PerlWarn and PerlTaintCheck see Switches -w, -T
See Tuning the Apache's configuration variables for the best performance
It is advised not to publish the 8080 (or alike) port number in URLs, but rather using a proxying rewrite rule in the thin (httpd_docs) server:
RewriteRule .*/perl/(.*) http://my.url:8080/perl/$1 [P]
One problem with publishing 8080 port numbers is that I was told that IE 4.x has a bug when re-posting data to a non-port-80 url. It drops the port designator, and uses port 80 anyway.
With <Perl></Perl>
sections, it is possible to configure your server entirely in Perl.
<Perl> sections can contain *any* and as much Perl code as you wish. These
sections are compiled into a special package whose symbol table mod_perl
can then walk and grind the names and values of Perl variables/structures
through the apache core configuration gears. Most of the configurations
directives can be represented as scalars ($scalar) or lists (@list). An @List
inside these sections is simply converted into a space delimited string for
you inside. Here is an example:
#httpd.conf <Perl> @PerlModule = qw(Mail::Send Devel::Peek); #run the server as whoever starts it $User = getpwuid($>) || $>; $Group = getgrgid($)) || $); $ServerAdmin = $User; </Perl>
Block sections such as <Location
..</Location>> are represented in a
%Location
hash, e.g.:
$Location{"/~dougm/"} = { AuthUserFile => '/tmp/htpasswd', AuthType => 'Basic', AuthName => 'test', DirectoryIndex => [qw(index.html index.htm)], Limit => { METHODS => 'GET POST', require => 'user dougm', }, };
If a Directive can take two *or* three arguments you may push strings and
the lowest number of arguments will be shifted off the @List
or use array reference to handle any number greater than the minimum for
that directive:
push @Redirect, "/foo", "http://www.foo.com/"; push @Redirect, "/imdb", "http://www.imdb.com/"; push @Redirect, [qw(temp "/here" "http://www.there.com")];
Other section counterparts include %VirtualHost
, %Directory
and
%Files
.
To pass all environment variables to the children with a single configuration directive, rather than listing each one via PassEnv or PerlPassEnv, a <Perl> section could read in a file and:
push @PerlPassEnv, [$key => $val];
or
Apache->httpd_conf("PerlPassEnv $key $val");
These are somewhat simple examples, but they should give you the basic
idea. You can mix in any Perl code your heart desires. See
eg/httpd.conf.pl
and eg/perl_sections.txt
in mod_perl distribution for some examples.
A tip for syntax checking outside of httpd:
<Perl> # !perl #... code here ... __END__ </Perl>
Now you may run:
perl -cx httpd.conf
To enable <Perl
> sections you should build mod_perl with perl
Makefile.PL PERL_SECTIONS=1.
You can watch how have you configured the <Perl
> sections through the /perl-status location, by choosing the Perl Sections from the menu.
You can dump the configuration by <Perl
> sections configuration this way:
<Perl> use Apache::PerlSections(); ... print STDERR Apache->PerlSections->dump(); </Perl>
Alternatively you can store it in a file:
Apache::PerlSections->store("httpd_config.pl");
You can then require()
that file in some other <Perl
> section.
mod_macro is an Apache module written by Fabien Coelho that lets you define and use macros in the Apache configuration file.
mod_macro proved really useful when you have many virtual hosts, each virtual host has a number of scripts/modules, most of them with a moderately complex configuration setup.
First download the latest version of mod_macro from http://www.cri.ensmp.fr/~coelho/mod_macro/ , and configure your Apache server to use this module.
Here are some useful macros for mod_perl users:
# set up a registry script <Macro registry> SetHandler "perl-script" PerlHandler Apache::Registry Options +ExecCGI </Macro>
# example Alias /stuff /usr/www/scripts/stuff <Location /stuff> Use registry </Location>
If your registry scripts are all located in the same directory, and your aliasing rules consistent, you can use this macro:
# set up a registry script for a specific location <Macro registry $location $script> Alias /script /usr/www/scripts/$script <Location $location> SetHandler "perl-script" PerlHandler Apache::Registry Options +ExecCGI </Location> </Macro>
# example Use registry stuff stuff.pl
If you're using content handlers packaged as modules, you can use the following macro:
# set up a mod_perl content handler module <Macro modperl $module> SetHandler "perl-script" Options +ExecCGI PerlHandler $module </Macro>
#examples <Location /perl-status> PerlSetVar StatusPeek On PerlSetVar StatusGraph On PerlSetVar StatusDumper On Use modperl Apache::Status </Location>
The following macro sets up a Location for use with HTML::Embperl. Here we define all ``.html'' files to be processed by Embperl.
<Macro embperl> SetHandler "perl-script" Options +ExecCGI PerlHandler HTML::Embperl PerlSetEnv EMBPERL_FILESMATCH \.html$ </Macro>
# examples <Location /mrtg> Use embperl </Location>
Macros are also very useful for things that tend to be verbose, such as setting up Basic Authentication:
# Sets up Basic Authentication <Macro BasicAuth $realm $group> Order deny,allow Satisfy any AuthType Basic AuthName $realm AuthGroupFile /usr/www/auth/groups AuthUserFile /usr/www/auth/users Require group $group Deny from all </Macro>
# example of use <Location /stats> Use BasicAuth WebStats Admin </Location>
Finally, here is a complete example that uses macros to set up simple virtual hosts. It uses the BasicAuth macro defined previously (yes, macros can be nested!).
<Macro vhost $ip $domain $docroot $admingroup> <VirtualHost $ip> ServerAdmin webmaster@$domain DocumentRoot /usr/www/htdocs/$docroot ServerName www.$domain <Location /stats> Use BasicAuth Stats-$domain $admingroup </Location> </VirtualHost> </Macro>
# define some virtual hosts Use vhost 10.1.1.1 example.com example example-admin Use vhost 10.1.1.2 example.net examplenet examplenet-admin
mod_macro also useful in a non vhost setting. Some sites for example have lots of scripts where people use to view various statistics, email settings and etc. It is much easier to read things like:
use /forwards email/showforwards use /webstats web/showstats
Check your configuration files and make sure that the ``ExecCGI'' is turned on in your configurations.
<Location /perl> SetHandler perl-script PerlHandler Apache::Registry Options ExecCGI allow from all PerlSendHeader On </Location>
Did you put PerlSendHeader On in the configuration part of the <Location foo></Location>?
No. Any virtual host will be able to see the routines from a startup.pl loaded for any other virtual host.
You can use 'PerlSetEnv PERL5LIB ...' or a PerlFixupHandler w/ the lib pragma.
Even a better way is to use Apache::PerlVINC
This has been a bug before, last fixed in 1.15_01, i.e. if you are running 1.15, that could be the problem. You should set this variable in a startup file (PerlRequire):
$Apache::Registry::NameWithVirtualHost = 1;
But, as we know sometimes bug turns into a feature. If there is the same script running for more than one Virtual host on the same machine, this can be a waste, right? Set it to 0 in a startup script if you want to turn it off and have this bug as a feature. (Only makes sense if you are sure that there will be no otherscripts named by the same path/name). It also saves you some memory on the way.
$Apache::Registry::NameWithVirtualHost = 0;
The problem was reported by users who declared mod_perl configuration inside a <Directory> section for all files matching to *.pl. The problem has gone away after placing the usage of mod_perl in a <File>- section.
It is better not to advertise the port mod_perl server running at to the
outside world for it creates a potential security risk by revealing which
module(s)
and/or OS you are running your web server on.
The more modules you have in your web server, the more complex the code in your webserver.
The more complex the code in your web server, the more chances for bugs.
The more chance for bugs, the more chance that some of those bugs may involve security.
Never was completely sure why the default of the ServerToken directive in Apache is Full rather than Minimal. Seems like you would only make it full if you are debugging.
For more information see Publishing port numbers different from 80
Another approach is to modify httpd sources to reveal no unwanted
information, so if you know the port the HEAD
request will return an empty or phony Server:
field.
Let's say that you want all the file in a specific directory and below to be handled the same way, but a few of them to be handled somewhat different. For example:
<Directory /home/foo> <FilesMatch "\.(html|txt)$"> SetHandler perl-script PerlHandler Apache::AddrMunge </FilesMatch> </Directory>
Alternatively you can use <Files> inside an .htaccess
file.
Note that you cannot have Files
derective inside Location
, but you can have Files
inside Directory
.
When the server is restarted. the configuration and module initialization phases are called again (twice in total). To ensure that the future restart will workout correctly, Apache actually runs these two phases twice during server startup, to check that all modules can survive a restart.
(META: And add an example that writes to the log file - I was restarted 1, 2 times)
|
||
Written by Stas Bekman.
Last Modified at 09/26/1999 |
![]() |
Use of the Camel for Perl is a trademark of O'Reilly & Associates, and is used by permission. |